核心是os.Stat()获取目标文件信息、os.Lstat()获取符号链接自身元数据;需用errors.Is(err, os.ErrNotExist)准确判断不存在,而非仅检查err!=nil。

Go 里检查文件属性,核心就靠 os.Stat() 和 os.Lstat(),别用 os.IsNotExist() 这类快捷函数做复杂判断——它们只是包装,掩盖了真实状态。
用 os.Stat() 获取完整文件信息
它返回一个 os.FileInfo 接口,包含大小、模式、修改时间等全部元数据。注意:遇到符号链接时,它会自动解引用,返回目标文件的信息。
常见错误是只检查 err != nil 就认为文件不存在,但其实 err 可能是权限拒绝(permission denied)或设备忙(device busy),和“不存在”性质完全不同。
- 正确做法:先调用
os.Stat(),再用errors.Is(err, os.ErrNotExist)判断是否真不存在 - 若需区分“无权访问”和“不存在”,不能只看
err == nil或err != nil - 返回的
os.FileInfo是只读快照,不随文件后续变化而更新
os.Lstat() 专用于符号链接元信息
当路径指向符号链接时,os.Lstat() 返回的是链接自身的属性(比如链接文件的大小、创建时间),而不是它指向的目标。这是唯一能安全获取链接本身信息的方式。
立即学习“go语言免费学习笔记(深入)”;
典型使用场景:实现类似 ls -L(跟随链接) vs ls -d(仅链接自身)的行为;或者校验链接路径是否合法但不触发目标访问(如避免挂载点卡住)。
- 对普通文件或目录,
os.Lstat()和os.Stat()行为一致 - 若链接目标不存在(悬空链接),
os.Lstat()仍成功,os.Stat()则返回os.ErrNotExist - Windows 下符号链接支持依赖于系统权限和创建方式,
Lstat()可能返回not supported
从 os.FileInfo.Mode() 提取权限与类型
Mode() 返回 os.FileMode,它既是权限掩码(低 9 位),也携带文件类型标志(如 os.ModeDir、os.ModeSymlink)。直接用 & 位运算比字符串匹配更可靠。
容易踩的坑是误把 fi.Mode()&os.ModePerm 当成“可执行位”,其实这只是用户/组/其他三组的 rwx 权限;真正判断是否可执行,应结合操作系统(如 Unix 下看 x 位,Windows 下通常忽略)。
- 判断是否目录:
fi.Mode().IsDir()(推荐)或fi.Mode()&os.ModeDir != 0 - 判断是否符号链接:
fi.Mode()&os.ModeSymlink != 0(IsDir()对链接返回 false) - 检查可写性不要只看 mode:即使 mode 有 w 位,也可能因父目录不可写或挂载为只读而失败
文件属性检查不是原子操作——两次 Stat() 调用之间,文件可能已被删除、重命名或权限变更。需要强一致性时,得配合文件锁或 open+syscall.fstat(但后者跨平台成本高)。另外,os.FileInfo 不包含 inode、硬链接数、扩展属性等,这些得用 syscall.Stat() 或第三方包(如 golang.org/x/sys/unix)深入获取。


















