应检查os.stat的err是否为nil,区分os.isnotexist和os.ispermission等错误类型;modtime需truncate或转utc以保跨平台一致;仅用modtime比对不可靠,应结合大小或哈希;避免time.now精度陷阱。

如何用 os.Stat 安全获取文件修改时间
直接调用 os.Stat 是最常用方式,但它会返回错误(比如文件不存在、权限不足),不能忽略。尤其在比对逻辑中,一个失败就可能导致误判为“已更新”或“未变化”。
- 务必检查
err != nil,不要只看FileInfo是否为空 -
FileInfo.ModTime()返回的是time.Time,纳秒级精度,但多数场景下秒级足够;若需跨平台一致比对,建议用.Truncate(time.Second) - 注意:符号链接默认会被解析(即返回目标文件时间),如需链接自身时间,改用
os.Lstat
比对两个文件是否“内容未变”:仅靠 ModTime 不可靠
修改时间相同 ≠ 内容相同。用户可能手动 touch 文件、备份工具重写时间戳、NFS 挂载时钟不同步——这些都会让 ModTime 失效。
- 若业务要求强一致性(如配置热重载、资源校验),必须配合其他依据:文件大小 +
ModTime双校验,或加sha256哈希(小文件适用) - 仅比对
ModTime适合低敏感场景(如日志轮转触发、临时缓存刷新) - 注意时区无关性:
time.Time默认带 location,但ModTime()总是本地时区?不,它来自系统 stat 结构,Go 会转为time.Local;跨机器比对建议统一转为 UTC:fi.ModTime().UTC()
处理“文件不存在”时的典型误判逻辑
常见写法:if err != nil { return true // 视为“已变更”}——这会导致首次运行或路径错配时强制触发更新,很危险。
- 应区分错误类型:
os.IsNotExist(err)表示文件刚创建/被删,此时比对无意义,需明确策略(如返回 error、跳过、或视为“旧版本不存在”) - 权限错误(
os.IsPermission(err))更应报错退出,而不是静默当作“变更” - 推荐封装成函数,显式返回三种状态:
Changed/Unchanged/Unknown(对应 error)
避免 time.Now() 和 ModTime() 的精度陷阱
在高频写入场景(如单元测试快速创建+修改文件),time.Now() 和 os.Stat 获取的时间可能落在同一纳秒或微秒内,导致 t1.After(t2) 判断失效。
- 不要用
time.Now().After(fi.ModTime())判断“是否刚写入”,应改用time.Since(fi.ModTime()) - Linux ext4 默认时间戳精度是纳秒,但某些文件系统(如 FAT32、某些 NFS)只有 2 秒或 1 天精度,
ModTime()可能被向下取整 - 若需严格顺序保障(如 watch + process 流程),应在写入后主动
syscall.Sync()或使用os.WriteFile(内部含fsync)
实际比对逻辑里最容易被忽略的,是把“时间戳相等”直接等价于“内容未变”。哪怕只是加一行日志,也值得多一次 os.Stat 查大小——它几乎零开销,却能拦住 90% 的假阳性。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











