os.Stat是获取文件权限和时间的首选方式,它一次调用返回完整元数据:用Mode().Perm()提取权限位、ModTime()获取修改时间(time.Time类型),并提供IsDir()等安全方法;需检查error,且注意ModTime精度与时区问题。

os.Stat 是获取文件权限和时间的首选方式
别自己调用 syscall.Stat 或 syscall.Lstat —— Go 标准库的 os.Stat 已经封装好跨平台行为,且默认跟随符号链接、自动处理 Windows/Unix 差异。直接用它最稳妥。
常见错误是误以为 os.Stat 只能拿修改时间,其实它一次调用就返回完整元数据:
-
info.Size():逻辑大小(普通文件即字节数) -
info.Mode().Perm():提取用户/组/其他三类权限位(如0644),Mode()还含目录、符号链接等标志位 -
info.ModTime():修改时间,返回time.Time,注意是本地时区,不是 UTC -
info.IsDir()、info.Mode().IsRegular()等方法比手动位运算更安全
如果路径不存在或无权限,os.Stat 返回非 nil error,必须检查:os.IsNotExist(err) 判断是否真不存在,err == nil 才能继续用 info。
需要访问时间(atime)或创建时间(ctime)时才碰 syscall.Stat_t
os.FileInfo 接口不暴露访问/创建时间,必须通过 info.Sys() 拿底层结构体。但类型断言高度依赖操作系统:
立即学习“go语言免费学习笔记(深入)”;
- Linux/macOS:
stat, ok := info.Sys().(*syscall.Stat_t),然后读stat.Atim(访问)、stat.Ctim(状态变更,常被当作创建时间) - Windows:
win, ok := info.Sys().(*syscall.Win32FileAttributeData),读win.CreationTime和win.LastWriteTime - macOS 10.13+ 支持
birthtime,但需用syscall.Statfs_t或 cgo,标准库不提供
注意:Atim 在 Linux 上可能被挂载选项禁用(如 noatime),此时返回旧值或零值;Ctim 不是创建时间,而是 inode 元数据最后变更时间(如权限修改、硬链接增减)。
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
权限解析别手写位运算
info.Mode() 返回 os.FileMode,它本质是 uint32,但 Go 提供了语义化方法:
- 用
info.Mode().Perm()提取权限位(去掉目录、symlink 等标志),再跟0644比较 - 判断是否可执行:
info.Mode()&0111 != 0(比info.Mode().Perm()&0111更准,因为某些系统会把 sticky bit 存在 Perm 外) - Windows 下
Mode().Perm()总是0,权限靠 ACL 或syscall查,别指望它返回有意义值
错误示例:if info.Mode() == 0644 —— 忽略了目录位(0x8000)和 symlink 位(0xa000),永远不成立。
ModTime 精度和时区容易被忽略
info.ModTime() 的精度由文件系统决定:ext4 默认秒级,XFS 可达纳秒,NTFS 在 FAT 兼容模式下可能只有 2 秒精度。别假设它总能区分毫秒级改动。
它返回的是本地时区时间,不是 UTC:
- 打印时自动按本地时区格式化(如
2026-06-11 19:58:00 +0800 CST) - 跨时区比较必须先转 UTC:
info.ModTime().UTC() - 存数据库或序列化时,建议显式转 Unix 时间戳:
info.ModTime().UnixMilli()
真正难搞的是:ModTime() 对 NFS、FUSE、某些容器卷可能返回缓存值,甚至滞后数秒 —— 如果业务强依赖精确时间,得加额外校验或换用 inotify/fsevents。

















