用 errors.Is(err, fs.ErrNotExist) 判断不存在,errors.Is(err, fs.ErrPermission) 判断权限不足;os.Stat 后据此区分路径不存在或存在但无权访问;filepath.WalkDir 中遇权限错误可 return err 中断或收集;os.MkdirAll 权限受 umask 影响。

os.Open 返回 *os.PathError 时怎么判断是不存在还是权限不足
直接看 err 的底层类型和 Err 字段,别用字符串匹配错误信息。Go 标准库返回的多数路径错误都是 *os.PathError,它嵌套了真实的底层错误(比如 syscall.ENOENT 或 syscall.EACCES)。
- 用
errors.Is(err, fs.ErrNotExist)判断“文件或目录不存在”——这是最可靠的方式,兼容不同操作系统 - 用
errors.Is(err, fs.ErrPermission)判断“权限不足”,比如对目录无读权限、对文件无执行权限等 - 避免写
strings.Contains(err.Error(), "no such file"):Windows 错误信息是英文但格式不固定,中文系统下更不可靠 -
fs.ErrNotExist和fs.ErrPermission是变量,不是常量,必须用errors.Is比较,不能用==
os.Stat 失败后如何区分“路径不存在”和“路径存在但 Stat 被拒绝”
os.Stat 在遇到符号链接循环、权限不足、设备忙等情况时都可能失败,但只有“目标路径完全不存在”才该归为 not-found 类错误;其他属于访问控制或状态异常。
- 先调用
os.Stat(path),如果 err 为 nil,说明路径存在且可 stat —— 注意:这不代表可读/可写 - 如果 err 非 nil,再用
errors.Is(err, fs.ErrNotExist)判断是否真不存在 - 若不是
fs.ErrNotExist,但errors.Is(err, fs.ErrPermission)成立,说明路径存在,只是当前用户没权限获取元信息(常见于 root 创建的严格权限目录) - 还有一种情况:
err是*os.PathError,但Err是syscall.ELOOP(循环软链)或syscall.ENOTDIR(中间某段是文件非目录),这些都不该当成 “not found” 处理
filepath.WalkDir 遇到权限错误时默认跳过,怎么让它中断或收集错误
filepath.WalkDir 的回调函数返回非 nil error 时,会根据错误值决定行为:返回 filepath.SkipDir 跳过当前目录,返回其他 error 则终止遍历。但它不会主动暴露错误类型,得自己判断。
- 在
WalkDirFunc中收到err时,先检查是否为*fs.PathError,再用errors.Is(err, fs.ErrPermission) - 如果想遇到权限问题就立刻停止,直接 return
err(不用包装)即可 ——WalkDir会原样返回它 - 如果想继续遍历但记录所有权限错误,需在外层定义一个
sync.Mutex+ 切片,把errors.Is(err, fs.ErrPermission)的错误 append 进去 - 注意:
filepath.WalkDir不会为根路径本身调用回调;如果根路径就权限不足,WalkDir直接返回 error,根本不会进回调
os.MkdirAll 创建嵌套目录时,权限掩码为什么在 Linux 和 macOS 上表现不同
os.MkdirAll(path, perm) 的 perm 参数不是最终目录权限,而是传给 os.Mkdir 的 mode,实际生效受进程 umask 影响,且不同系统对“中间目录”和“叶子目录”的权限处理逻辑有差异。
立即学习“go语言免费学习笔记(深入)”;
- Linux/macOS 默认 umask 是
022,所以即使传0777,创建出来的目录权限通常是0755 - 中间目录(如
a/b/c中的a和a/b)权限始终按perm &^ umask计算;但某些旧版 Go(0755 掩码,导致传0700也可能变成0755 - 真正可控的方式:先
os.MkdirAll,再用os.Chmod显式设置最终目录权限(注意:只对叶子目录调用,避免影响父级) - 如果要确保跨平台一致,建议统一用
0755或0700,并接受 umask 的影响;不要依赖0777得到完全开放权限
error 值在不同系统上可能由不同 syscall 错误包装而来,而 errors.Is 背后依赖的是 Go 运行时对各平台 errno 的标准化映射 —— 这个映射表并不对外公开,所以永远别绕过它去手动比较 errno。










