os.Stat 是获取文件大小的首选方式,返回 os.FileInfo 的 Size() 方法,不打开文件、仅读元数据;注意目录返回自身 inode 大小而非子项总和,符号链接默认解析目标,需权限与存在性检查。

用 os.Stat 获取文件大小最常用
绝大多数场景下,os.Stat 是获取文件大小的首选方式。它返回一个 os.FileInfo 接口,其中 Size() 方法直接给出字节数。
注意:该方法不打开文件,只读取元数据,速度快、开销小。
常见错误是传入目录路径却期望得到“总大小”——os.Stat 对目录返回的是其自身 inode 占用(通常 4KB 左右),不是子项合计。
- 确保路径存在且有读权限,否则会返回
*os.PathError - 若路径是符号链接,默认解析目标;如需获取链接文件本身大小,用
os.Lstat - 示例:
info, err := os.Stat("config.json") if err != nil { log.Fatal(err) } size := info.Size() // int64 类型
用 os.Open + Stat() 适合已打开文件
当你已经通过 os.Open 打开了一个 *os.File,可以直接调用它的 Stat() 方法——这比再用 os.Stat 多一次系统调用更高效。
立即学习“go语言免费学习笔记(深入)”;
典型场景:读取配置、处理上传临时文件、流式解析前预判体积。
-
*os.File.Stat()返回的os.FileInfo和os.Stat()一致,Size()可靠 - 注意:某些文件系统(如 procfs、某些网络文件系统)可能不支持该字段,
Size()返回 0 或负值,需额外判断 - 示例:
f, err := os.Open("data.bin") if err != nil { log.Fatal(err) } defer f.Close() info, _ := f.Stat() size := info.Size()
大文件或不确定路径时,避免 os.Stat 的权限/存在性陷阱
os.Stat 在路径不存在、无权限、是挂起的 NFS 路径等情况下会直接报错,导致逻辑中断。生产环境应预判这些失败。
尤其在遍历目录或处理用户输入路径时,不能假设 os.Stat 一定成功。
- 用
errors.Is(err, os.ErrNotExist)或errors.Is(err, os.ErrPermission)做精准判断 - 不要用
err == nil粗暴断言成功;某些文件系统返回syscall.EOVERFLOW(如 32 位系统上 >2GB 文件) - 若只需“是否存在且可读”,可用
os.ReadFile配合io.EOF判断,但代价是实际读内容——仅当顺带需要内容时才划算
filepath.WalkDir 中获取每个文件大小要小心游标位置
使用 filepath.WalkDir 遍历时,回调函数接收的 fs.DirEntry 默认不包含大小信息。想拿到大小,必须显式调用 entry.Info() ——但这会触发一次额外 stat 系统调用。
更高效的做法是:在遍历前就用 os.Stat 拿到根目录信息,或改用 filepath.Walk(已弃用但兼容旧代码),或接受 Info() 的开销。
-
DirEntry.Info()可能返回nil(例如无法访问子项),需判空 - 如果只需要文件名和大小,且层级浅,用
os.ReadDir+ 并发os.Stat通常更快 - 示例中别漏掉
err检查:err := filepath.WalkDir(".", func(path string, d fs.DirEntry, err error) error { if err != nil { return err } if !d.IsDir() { info, err := d.Info() // 注意这里可能 err != nil if err != nil { return err } fmt.Printf("%s: %d\n", path, info.Size()) } return nil })
os.Stat 的行为在符号链接、权限边界、特殊文件系统上容易出人意料;真正上线前,务必用真实环境中的异常路径(如只读挂载、断开的 NFS、proc 文件)跑一遍测试。










