os.Stat是获取文件基础元数据的首选方法,返回包含Name()、Size()、Mode()、ModTime()等字段的FileInfo接口,不读取文件内容、性能高;需检查错误、区分符号链接(用Lstat)、正确解析Mode位和跨平台差异。

用 os.Stat 获取基础元数据最直接
Go 标准库的 os.Stat 是获取文件元数据的首选,它返回 os.FileInfo 接口,包含名称、大小、模式、修改时间等核心字段。注意它不读取文件内容,只访问文件系统元信息,速度快且安全。
- 调用
os.Stat("/path/to/file")返回os.FileInfo和可能的错误,必须检查错误(比如路径不存在或权限不足) -
FileInfo.Size()返回字节数,对目录也有效(但值无意义,仅表示目录项数量的近似) -
FileInfo.ModTime()是time.Time类型,可直接比较或格式化,无需额外解析 - 避免用
os.Lstat除非你明确需要符号链接本身的元数据(而非目标文件)
区分普通文件、目录、符号链接要用 FileInfo.Mode()
FileInfo.Mode() 返回的是位掩码,不是字符串类型,不能用 == "dir" 这类方式判断。正确做法是用预定义常量做位与运算。
- 判断是否为目录:
fi.Mode().IsDir()(推荐,语义清晰) - 判断是否为普通文件:
fi.Mode().IsRegular() - 判断是否为符号链接:
fi.Mode()&os.ModeSymlink != 0(IsSymlink()在 Go 1.19+ 才有,旧版本需手动判断) - 误用
fi.Mode().String()可能返回类似"drwxr-xr-x"的字符串,但该字符串格式不保证稳定,不应依赖其解析权限
获取 Unix 权限和用户/组 ID 需类型断言到 *os.FileStat
os.FileInfo 接口本身不暴露底层权限位或 UID/GID,必须将接口转为具体类型 *os.FileStat(Linux/macOS 下实际返回的类型)才能访问这些字段。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
- 先做类型断言:
if stat, ok := fi.(*os.FileStat); ok { ... } - 权限位:用
stat.Sys().(*syscall.Stat_t).Mode(Unix)或stat.Sys().(*syscall.Win32FileAttributeData)(Windows),跨平台时建议封装判断逻辑 - UID/GID:同上路径,通过
syscall.Stat_t.Uid和syscall.Stat_t.Gid获取,注意 Windows 不提供等价概念 - 不做断言直接访问会 panic;也不建议全局强制转换,应先
ok判断
批量读取大量文件时慎用 os.Stat,考虑 filepath.WalkDir
逐个调用 os.Stat 在遍历目录树时会产生大量系统调用,性能较差。Go 1.16 引入的 filepath.WalkDir 在首次访问目录时就批量读取所有条目及其元数据(含 DirEntry),比传统 Walk 更高效。
立即学习“go语言免费学习笔记(深入)”;
-
filepath.WalkDir(root, func(path string, d fs.DirEntry, err error) {...})中的d已含基础元数据,调用d.Info()才触发一次Stat(可选) - 若只需判断类型或名字,直接用
d.IsDir()、d.Name(),避免多余Info()调用 - Windows 上
WalkDir使用FindFirstFile,Linux/macOS 使用readdir,均比反复stat系统调用更轻量 - 注意
DirEntry.Info()仍可能返回错误(如权限不足),不能假设一定成功
真正难的不是怎么拿元数据,而是判断哪些字段真要、哪些平台能用、哪些调用其实多余——尤其在混合部署或跨平台打包场景下,os.FileStat 断言和 syscall 层访问最容易出隐蔽问题。

















