用 os.Stat 判断文件是否存在是最常用且最稳妥的方式,需用 errors.Is(err, os.ErrNotExist) 精确判断“不存在”,而非仅检查 err != nil,以避免误判权限拒绝等其他错误。

用 os.Stat 判断文件是否存在是最常用也最稳妥的方式
直接调用 os.Stat 获取文件信息,再检查错误是否为 os.ErrNotExist,这是 Go 官方推荐的做法。它不依赖文件权限或路径类型(普通文件、目录、符号链接都适用),且行为一致。
常见错误是只判断 err != nil 就认为文件不存在——这会误判权限拒绝、I/O 错误等其他情况。
-
os.Stat返回os.FileInfo和error;只要err == nil,说明路径存在且可访问 - 若
err != nil,需用errors.Is(err, os.ErrNotExist)精确判断是否“不存在”(Go 1.13+) - 旧版本(os.IsNotExist(err)
- 注意:
os.Stat对目录也返回成功,所以它判断的是“路径存在”,不是“是文件”
想严格区分“文件”和“目录”?得结合 FileInfo.IsDir()
os.Stat 本身不告诉你是不是普通文件,只给一个 os.FileInfo 接口。要确认是文件而非目录,必须额外调用 IsDir() 方法。
典型场景:读取配置文件前,既要确保路径存在,又要防止用户传入目录导致后续 os.Open 失败。
立即学习“go语言免费学习笔记(深入)”;
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 先
fi, err := os.Stat(path) - 再
if err != nil || fi.IsDir()→ 不是普通文件 - 注意:
fi.Mode()&os.ModeType == 0可进一步排除设备文件、命名管道等特殊类型,但多数场景只需!fi.IsDir()
os.IsNotExist 不是函数,是用于错误判断的工具函数
很多人误以为 os.IsNotExist 是个能直接传路径进去的判断函数,其实它只是对 error 做类型检查的辅助函数,必须配合 os.Stat 或其他 I/O 操作一起用。
错误写法:if os.IsNotExist("/path/to/file") { ... } —— 这会编译失败。
- 正确用法:
_, err := os.Stat(path); if os.IsNotExist(err) { ... } - Go 1.13+ 更推荐
errors.Is(err, os.ErrNotExist),支持嵌套错误(比如fmt.Errorf("read config: %w", err)) - 别用
err.Error() == "file does not exist"—— 错误消息可能随系统语言或 Go 版本变化
性能敏感时别反复调用 os.Stat,考虑缓存或一次性批量检查
每次 os.Stat 都触发一次系统调用,在高频路径检查(如 Web 请求中校验上传文件名)下会有明显开销。但 Go 没有内置文件存在性缓存机制,得自己权衡。
- 短生命周期程序(CLI 工具)无需缓存,直接调用即可
- 长期运行服务(如 API server)若频繁检查同一组路径,可用
map[string]bool缓存结果,但要注意文件可能被外部修改 - 批量检查多个路径时,避免循环里反复
os.Stat,可考虑并发(sync.WaitGroup+ goroutine),但注意系统限制和磁盘压力
真正容易被忽略的是:即使 os.Stat 返回存在,下一毫秒文件也可能被删或改权限——所有存在性检查本质都是“瞬时快照”,业务逻辑得容忍这种竞态。

















