os.MkdirAll是创建嵌套路径的唯一可靠方式,它递归创建所有缺失父目录、路径已存在时静默成功,避免TOCTOU竞态;而os.Mkdir仅建最后一级,父目录缺失即报“no such file or directory”。

os.MkdirAll 是写入文件前创建多级目录的唯一可靠方式,别用 os.Mkdir ——它遇到任意一级父目录缺失就直接报 "no such file or directory"。
为什么必须用 os.MkdirAll 而不是 os.Mkdir
真实路径如 "logs/error/2026/09" 或 "cache/images/thumbnails" 天然嵌套三层以上。用 os.Mkdir 尝试创建,只要 logs/ 不存在,立刻失败;os.MkdirAll 会自动补全 logs → logs/error → logs/error/2026,再建最后一级。
-
os.MkdirAll返回nil表示“成功创建”或“路径已存在”,都不是错误 - 需显式判断错误类型:
os.IsExist(err)可安全忽略,“已存在”不等于失败 - 若路径来自用户输入或配置,务必先过
filepath.Clean(),防../跳出预期范围
os.MkdirAll 的权限参数怎么写才对
权限必须是 os.FileMode 类型,不是裸整数。写 0755 没问题,但写 755(十进制)会被解释为八进制 01143,导致目录不可遍历(截至 2026 年 6 月)。
- 推荐用八进制字面量:
0755、0644、os.ModePerm - 避免用
0o755(Go 不支持该语法),也别用fs.ModeDir | 0755(类型不匹配) - 跨平台路径请用
filepath.Join("logs", "error", "2026", "09")构建,而非硬拼"logs/error/2026/09"
完整写入前检查与创建流程
不能只调 os.MkdirAll 就完事——得结合 os.Stat 和错误判断,尤其当路径含符号链接时,os.MkdirAll 会在解析后位置创建,若目标挂载点只读,仍会报 syscall.EROFS。
立即学习“go语言免费学习笔记(深入)”;
- 先
filepath.Clean()规范路径 - 再
os.MkdirAll(path, 0755),检查是否为os.IsNotExist或os.IsPermission - 必要时用
filepath.EvalSymlinks(path)提前展开并确认挂载点可写 - 最后才
os.Create或os.OpenFile写入文件
最易被忽略的是:路径中含符号链接时,os.MkdirAll 不报错也不提示,但它创建的位置可能完全不在你预期的磁盘分区上——务必在关键路径上加 filepath.EvalSymlinks 验证目标实际位置。


















