必须用 errors.Is(err, os.ErrNotExist) 判断路径不存在,而非 err != nil;因 os.Stat 失败还可能是权限不足、坏链接、NFS 断开等,这些错误需单独处理,误判会导致逻辑错误。

os.Stat 判断路径存在性时为什么总误判?
直接用 err != nil 就认为路径不存在,是最大误区。真实场景中,os.Stat 失败可能是权限不足、符号链接断裂、设备忙,甚至网络挂载断开——这些都不是“不存在”。
- 必须用
errors.Is(err, os.ErrNotExist)或os.IsNotExist(err)显式判断“不存在” - 其他错误(比如
syscall.EACCES)要单独处理,不能一概跳过 - 对用户输入的路径,先用
filepath.Clean规范化,再os.Stat,避免../或空段导致意外失败 - 别在
os.MkdirAll后立刻os.Stat—— 并发下可能因竞态返回os.ErrNotExist,需加简单重试或改用os.ReadDir验证子项
os.ReadDir 为什么返回空或 panic?
os.ReadDir 只接受目录路径,传入文件、空字符串、相对路径未校验,都会直接 panic 或返回 *os.PathError,错误信息通常是 "not a directory" 或 "no such file or directory"。
- 调用前必须先
os.Stat(path)+info.IsDir()双重校验:存在且是目录 - 它返回
[]fs.DirEntry,不触发stat系统调用,比老式os.Readdirnames更轻量,但无法直接拿到文件大小、修改时间 - 如需完整元数据,对每个
entry单独调用entry.Info()(会触发一次系统调用) - Windows 下若路径含长文件名或 UNC 路径,需确保启用长路径支持,必要时加
\?\前缀
os.Mkdir 和 os.MkdirAll 的权限参数怎么写才不翻车?
写成 755 是十进制,等价于八进制 01137,实际权限完全失控;正确写法必须带前导 0,即 0755。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
-
os.Mkdir("a/b", 0755):只创建b,要求a已存在,否则报"no such file or directory" -
os.MkdirAll("a/b/c", 0755):自动创建全路径,推荐用于输出目录初始化 - 权限值建议用位或组合增强可读性,例如
0755 | os.ModeDir(虽冗余,但意图明确) - 父目录权限太严(如
0700)会限制子目录访问——最终可访问性由路径上每一级权限共同决定
os.RemoveAll 删除后为什么还有残留?
os.RemoveAll 是“尽力而为”操作:遇到只读文件、进程占用、权限拒绝时,它不会中断,而是跳过并继续删其余项,最后只返回第一个错误(甚至返回 nil)。
立即学习“go语言免费学习笔记(深入)”;
- 绝不能只看
err == nil就认为删除成功;删除后必须验证,比如用os.ReadDir检查是否为空目录 - Windows 上常见
ERROR_ACCESS_DENIED,多因文件被 IDE、日志轮转或系统进程锁定 - 容器或挂载卷中,
/tmp等路径若被noexec或nosuid挂载,可能导致子目录权限判定异常 - 删除后立即
os.Stat可能因内核缓存返回旧状态,建议加毫秒级重试或换用os.ReadDir验证
filepath.Join 必须替代字符串拼接,0755 的前导零不能省,而 os.RemoveAll 的“静默跳过”行为在 CI 或 Windows 环境下最容易暴露问题**。

















