disk.usage()比unix.statfs更稳,因其跨平台统一处理windows/linux/macos路径解析、权限异常和挂载点识别,自动返回真实可用空间available,避免手动适配系统调用差异。

直接用 github.com/shirou/gopsutil/v3/disk 的 disk.Usage(),别自己封装 unix.Statfs 或调 df 命令——跨平台、防符号链接、自动处理 Windows 权限和挂载点识别,出错率低得多。
为什么 disk.Usage() 比 unix.Statfs 更稳
unix.Statfs 在 Linux/macOS 上能用,但一到 Windows 就编译失败;硬切 //go:build windows 写 syscall.GetDiskFreeSpaceEx,又得手动 resolve 路径、处理 ERROR_ACCESS_DENIED(它不被 os.IsPermission 覆盖)、区分卷名格式(C: vs C:\)。而 disk.Usage() 内部已做这些:Windows 下优先走 Win32 API,失败时回退 WMI;Linux/macOS 自动解析软链接并跳过 bind mount;所有平台统一返回 Available 字段(即非 root 用户真实可写空间)。
- 传入路径必须是挂载点,如
"/"、"C:",不是/tmp/foo或/dev/sda1—— 后者会报ErrNotFound或返回根设备数据 - 别依赖
Percent做告警:它按(Total - Free) / Total算,但Free包含 root 保留块(默认 5%),实际服务可用的是Available - 容器环境(尤其 rootless Pod)下
err != nil很常见,此时应降级处理,不能直接 panic 或忽略
如何避免监控采样漂移和积压
用 time.Sleep(5 * time.Second) 轮询会导致周期漂移:每次 disk.Usage() 耗时几十毫秒,1 小时后可能偏移 2–3 秒;若某次卡在 NFS 挂起上,后续所有 tick 会集中爆发执行。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 必须用
time.Ticker保证等间隔触发 - 但要在每次 tick 中加超时控制:
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) - 调用完立刻
cancel(),err != nil时continue,丢弃迟到 tick - 不要把
disk.Usage()放进 goroutine 异步跑——并发无意义,反而增加上下文切换和错误处理复杂度
告警阈值怎么设才不误报
只看单次 Available 容易被毛刺干扰;只看 <code>Percent > 90% 会被大分区稀释(比如 /home 占满但 /var/log 已只剩 100MB)。
- 关键路径单独监控:对
"/var/log"、"/var/lib/docker"这类服务强依赖路径设独立阈值 - 用连续判定:低于阈值的次数 ≥3 次才触发告警,恢复也需连续 3 次高于阈值
- 计算「剩余可用百分比」:用
float64(usage.Available) / float64(usage.Total) * 100,比usage.Percent更贴近真实水位 - 输出日志必须结构化(如 RFC3339 时间戳 + JSON),别用
fmt.Printf拼字符串——下游告警系统解析不了
真正难的不是“怎么拿到数字”,而是路径是否为挂载点、Available 是否被 cgroup 或 overlayfs 截断、以及 Windows 下管理员权限缺失时的静默失败——这些都藏在 err 里,不检查就等于没监控。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










