最准方法是用 unix.statfs 获取 linux/macos 磁盘总容量:传挂载点路径,total = s.blocks * s.frsize;windows 必须用 windows.getdiskfreespaceex;禁用 os.stat 和 filepath.walkdir 等错误方式。

用 unix.Statfs 获取 Linux/macOS 磁盘总容量(最准)
直接调用系统调用比任何包装库都更可靠,尤其在监控场景下不能容忍误差。Linux 和 macOS 都支持 unix.Statfs,它返回原始块数和块大小,计算结果与 df 一致。
关键点不是“能不能拿到”,而是“怎么算才对”:
-
statfs.Blocks是总块数,statfs.Frsize是文件系统基本块大小(不是Bsize),总容量 =statfs.Blocks * statfs.Frsize - 传入路径必须是挂载点(如
"/"、"/home"),不是任意目录;若路径跨挂载点(比如"/home/user/data"),Statfs返回的是/home所在文件系统的数据 - 必须检查错误:路径不存在、权限不足、NFS 挂载异常都会导致
unix.Statfs返回非 nil 错误,不处理会静默失效 - 示例片段:
var s unix.Statfs_t if err := unix.Statfs("/tmp", &s); err != nil { log.Printf("statfs failed: %v", err) return 0, err } total := uint64(s.Blocks) * uint64(s.Frsize)
Windows 上必须用 windows.GetDiskFreeSpaceEx
POSIX 的 Statfs 在 Windows 上不可用,硬切平台会 panic。Windows 原生 API 是 windows.GetDiskFreeSpaceEx,它直接返回字节数,无需换算。
注意几个实际约束:
- 路径需带盘符且结尾为反斜杠,如
"C:\\";传"C:"或"C:/temp"可能返回错误或默认盘信息 - 函数返回三个值:
freeBytesAvailable(非特权用户可用)、totalNumberOfBytes、totalNumberOfFreeBytes;监控用途应取totalNumberOfBytes作总容量 - 需启用 CGO(
CGO_ENABLED=1),否则golang.org/x/sys/windows无法链接系统 DLL - 构建时加
//go:build windows标签,避免在 Linux 构建时报 undefined symbol
别用 os.Stat 或 filepath.WalkDir 查磁盘容量
这两个函数根本不是为查磁盘设计的,但新手常误用:
-
os.Stat返回单个文件/目录的元数据(修改时间、权限、inode),不含任何挂载点级容量字段;调它一百次也得不到df -h的结果 -
filepath.WalkDir是遍历文件树用的,性能差(O(n))、不准(跳过无权限目录就少算)、易中断(遇到 symlink 循环或 permission denied 就 stop) - 有人试过
exec.Command("du", "-sb", path),问题更严重:依赖 shell、输出格式随 locale 变、没超时控制、容器里可能根本没du命令
要不要引入 gopsutil?看场景
如果你只跑在 Linux 服务器上做轻量监控,裸调 unix.Statfs 足够,零依赖、启动快、行为确定。
但以下情况建议用 github.com/shirou/gopsutil/v3/disk:
- 需要同时支持 Windows + Linux + macOS,且不想维护三套条件编译逻辑
- 要获取已用/剩余/使用率、inodes 使用情况、分区类型(ext4/xfs/ntfs)等扩展字段
- 项目已用
gopsutil查内存/CPU,保持统一接口风格
注意:它底层仍是封装了各平台系统调用,只是帮你做了路径归一化、错误映射和单位转换;但多一层抽象意味着多一个潜在故障点——比如新版 Windows 更新后某个字段语义变了,gopsutil 若未及时适配,你不会立刻发现。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











