应先解析路径再调用Statfs:用filepath.EvalSymlinks获取真实路径,再以该路径调用golang.org/x/sys/unix.Statfs(Linux/macOS)或windows.GetDiskFreeSpaceEx(Windows),计算可用空间为Bavail×Bsize或直接返回freeBytesAvailable。

用 Statfs 获取文件所在挂载点的磁盘空间信息
Go 标准库没有直接“根据文件路径查剩余空间”的函数,必须先获取文件所在挂载点(即分区)的文件系统信息。核心是调用 syscall.Statfs 或更推荐的跨平台封装 golang.org/x/sys/unix.Statfs(Linux/macOS)或 golang.org/x/sys/windows.GetDiskFreeSpaceEx(Windows)。但更简单可靠的做法是:先用 filepath.EvalSymlinks 解析路径,再用 os.Stat 拿到 os.FileInfo,最后通过 Statfs 查询其所在设备的文件系统统计。
Linux/macOS 下用 unix.Statfs 读取 f_bavail 字段
unix.Statfs 返回的结构体中,f_bavail 是普通用户可用的空闲块数(已扣除 root 保留空间),比 f_bfree 更贴近真实可用值。注意单位是“文件系统基本块大小”(f_bsize),不是字节,需换算:
import (
"golang.org/x/sys/unix"
"os"
"path/filepath"
)
<p>func getAvailableSpace(path string) (uint64, error) {
absPath, err := filepath.Abs(path)
if err != nil {
return 0, err
}
absPath, err = filepath.EvalSymlinks(absPath)
if err != nil {
return 0, err
}</p><pre class="brush:php;toolbar:false;">var statfs unix.Statfs_t
if err := unix.Statfs(absPath, &statfs); err != nil {
return 0, err
}
// f_bavail 是非 root 用户可用块数,f_bsize 是每块字节数
return uint64(statfs.Bavail) * uint64(statfs.Bsize), nil}
-
absPath必须是真实存在的路径,否则Statfs失败(哪怕父目录存在也不行) - 别误用
f_blocks * f_bsize算总空间——那是总块数,不含保留区,且未考虑实际使用 - macOS 上
unix.Statfs可用,但字段名略有不同(如Bavail对应f_bavail),x/sys 已做兼容
Windows 下必须用 GetDiskFreeSpaceEx
Windows 不支持 Statfs,得提取盘符并调用 Windows API。关键点是:不能直接对任意路径调用,要先用 filepath.VolumeName 提取卷名(如 C:),再传给 GetDiskFreeSpaceEx:
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
立即学习“go语言免费学习笔记(深入)”;
import "golang.org/x/sys/windows"
<p>func getAvailableSpaceWin(path string) (uint64, error) {
vol := filepath.VolumeName(path)
if vol == "" {
return 0, fmt.Errorf("no volume name in path: %s", path)
}
var freeBytesAvailable, totalBytes, totalFreeBytes uint64
err := windows.GetDiskFreeSpaceEx(windows.StringToUTF16Ptr(vol), &freeBytesAvailable, &totalBytes, &totalFreeBytes)
if err != nil {
return 0, err
}
return freeBytesAvailable, nil
}-
GetDiskFreeSpaceEx返回的freeBytesAvailable是“当前用户可用字节数”,已自动扣除配额和权限限制 - 若路径是 UNC 路径(
\servershare),VolumeName返回空,需额外处理(比如用windows.WNetGetConnection映射) - 跨平台项目建议用构建标签(
//go:build windows)隔离 Windows 逻辑
别忽略符号链接和 bind mount 的陷阱
如果目标路径是符号链接,os.Stat 默认返回链接自身信息(可能指向不存在路径),而 Statfs 会失败;必须用 filepath.EvalSymlinks 解析到真实路径。但更隐蔽的是 bind mount 或 overlayfs 场景:Linux 中一个路径可能属于某个子挂载点(如 /var/lib/docker/overlay2),Statfs 查到的是该子挂载点的剩余空间,而非根分区。这时需要向上遍历 /proc/mounts 找最近的父挂载点——标准库不提供此能力,得自己解析或依赖 github.com/shirou/gopsutil/disk 这类库。
实际部署时,最常被忽略的是:没检查路径是否存在就调 Statfs,错误返回 no such file or directory,而不是磁盘空间不足。先 os.Stat 确认路径有效,再查空间,顺序不能反。

















