os.stat返回的fileinfo不能直接指针比较,因其实现不保证指针唯一性;应使用os.samefile、inode比对或关键字段(如name)判断。

os.Stat 返回的 FileInfo 为什么不能直接用指针比较?
因为 os.Stat 返回的是接口类型 os.FileInfo,底层实际是 fs.FileInfo 的实现(如 syscall.Stat_t 或 fs.fileStat),它本身不保证指针唯一性。你拿到的两个 FileInfo 即使描述同一个文件,== 比较也大概率返回 false。
正确做法是比对关键字段:
- 用
fi1.Name() == fi2.Name()判断文件名是否一致(注意:不适用于硬链接或不同路径访问同一文件) - 更可靠的是用
fi1.Sys().(*syscall.Stat_t).Ino(Linux/macOS)或fi1.Sys().(*syscall.Win32FileAttributeData).FileIndexLow(Windows)比对 inode 或文件索引 - 或者统一走
os.SameFile(fi1, fi2)—— 这是 Go 标准库提供的安全判断方式
FileInfo.Size() 在目录上返回 0 是正常行为吗?
是的,完全正常。FileInfo.Size() 对目录的定义就是返回 0,不是 bug,也不是未实现。Go 的 os.FileInfo 接口把 Size() 定义为“常规文件的字节数”,而目录在大多数文件系统中并不以“字节大小”为第一语义(它的“大小”取决于条目数量、块分配等,且跨平台不一致)。
如果需要获取目录实际占用磁盘空间或子项数量,必须手动遍历:
- 用
filepath.WalkDir配合dirEntry.Info()累加文件大小(跳过目录自身) - 注意:不要用
os.ReadDir后对每个DirEntry调Info()——这会触发额外系统调用;优先用DirEntry.Type()和DirEntry.Info()的组合判断类型和基础属性 - Windows 下某些网络共享或 NTFS 压缩目录可能让
Size()表现异常,但仍是符合文档预期的
os.Stat 和 os.Lstat 的区别到底影响什么场景?
核心就一点:os.Stat 会跟随符号链接并返回目标文件的信息;os.Lstat 不跟随,返回符号链接自身的元数据(比如它自己的大小、创建时间、权限等)。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
典型误用场景:
- 想判断某路径是不是符号链接 → 必须用
os.Lstat,再检查fi.Mode()&os.ModeSymlink != 0;用os.Stat会直接跳到目标,永远得不到链接本身信息 - 备份工具需要保留符号链接结构 → 读取时用
Lstat,写入时用os.Symlink - Web 服务做路径校验(如防止目录穿越),若只用
Stat可能绕过检查:攻击者构造/var/www/../../etc/passwd的软链,Stat会直达目标,而Lstat能让你先看到“这是个链接”,再决定是否拒绝
FileInfo.ModTime() 的精度在不同系统上为什么差这么多?
因为 Go 直接复用操作系统底层的文件时间戳精度:FileInfo.ModTime() 底层来自 stat.st_mtime,而这个字段的分辨率由内核和文件系统共同决定。
常见表现:
- ext4 / XFS(Linux):通常支持纳秒级,但默认挂载参数可能降为秒级(如
noatime,relatime) - APFS / HFS+(macOS):纳秒级,但 Go
time.Time在序列化时可能截断 - FAT32 / exFAT:仅支持 2 秒或 10 毫秒级,
ModTime()读出来必有舍入误差 - NTFS(Windows):100 纳秒级,但 Go 运行时在某些版本存在转换偏差(如 1.19 之前
syscall.GetFileInformationByHandle返回值处理不完整)
如果你依赖高精度时间判断文件变更(比如增量同步),别只靠 ModTime() —— 加上 Size() 和 Ino() 组合校验,或改用 fsnotify 监听事件。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










