<p>应使用unix.Statfs(Linux/macOS)或windows.GetDiskFreeSpaceEx(Windows)获取磁盘总容量,因os.Stat和filepath.WalkDir不提供挂载点级数据;unix.Statfs需用s.Blocks * s.Frsize计算,路径必须为挂载点,且须检查错误;Windows需启用CGO并传入如"C:"格式路径。</p>

用 unix.Statfs 获取 Linux/macOS 总容量最准
别信 os.Stat 或 filepath.WalkDir 能查出磁盘总大小——它们压根不返回挂载点级数据。真正可靠的只有系统调用:unix.Statfs 返回原始块数和块大小,计算结果与 df 完全一致。
关键不是“调了没”,是“算得对不对”:
-
s.Blocks是总块数,s.Frsize是文件系统基本块大小(不是Bsize),总容量 =s.Blocks * s.Frsize - 路径必须是挂载点,比如
"/"、"/home";传"/home/user/data"会返回/home所在文件系统的数据,不是你想要的子目录所在设备 - 必须检查错误:路径不存在、权限不足、NFS 挂载异常都会让
unix.Statfs返回非nil错误,不处理就静默失效
Windows 上必须用 windows.GetDiskFreeSpaceEx
unix.Statfs 在 Windows 上不可用,硬切平台会 panic。Windows 原生 API 是 windows.GetDiskFreeSpaceEx,它直接返回字节数,不用换算。
但有硬约束:
立即学习“go语言免费学习笔记(深入)”;
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
- 路径必须带盘符且结尾为反斜杠,如
"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命令
跨平台封装要小心构建标签和导入路径
想写一个统一接口,不能简单 import 两边包然后 runtime 判断 OS——Go 编译器会尝试链接所有符号,导致 Windows 下编译 Linux 代码失败。
正确做法是条件编译 + 显式导入:
- Linux/macOS 文件用
//go:build !windows,导入golang.org/x/sys/unix,调unix.Statfs - Windows 文件用
//go:build windows,导入golang.org/x/sys/windows,调windows.GetDiskFreeSpaceEx - 别写错导入路径:
golang.org/x/sys/unix不是syscall,也不是golang.org/x/sys/unix/syscall - 标准库
syscall已弃用,且跨平台行为不一致;golang.org/x/sys/unix是官方维护的替代品,API 更稳定
实际最难的不是调用哪个函数,而是确保路径是挂载点、错误被显式处理、跨平台构建不炸,这三处漏掉任意一个,监控数据就不可信。

















