os.MkdirAll是创建多级目录的唯一合理选择,它自动逐级创建缺失父目录、已存在时返回nil、需用0o755格式权限、路径须clean处理且不带尾斜杠;而os.Mkdir仅建单层且父目录缺失即报错。

os.MkdirAll 是创建多级目录的唯一合理选择,别用 os.Mkdir ——它只建最后一层,父目录一缺就报 "no such file or directory"。
为什么 os.MkdirAll 必须替代 os.Mkdir
真实路径如 "logs/error/2026/06" 或 "cache/images/thumbnails" 天然嵌套多层。用 os.Mkdir 调用这类路径,只要 logs/ 不存在,立刻失败;而 os.MkdirAll 会自动补全 logs、logs/error、logs/error/2026,再建最后一级。
- 返回
nil表示“路径已存在”或“成功创建”,不是错误 - 错误类型需显式判断:
os.IsExist(err)可安全忽略,“已存在”不算失败 - 若路径来自用户输入或配置,务必先过
filepath.Clean(),防../跳出预期范围
os.MkdirAll 的权限参数怎么写才对
权限必须是 os.FileMode 类型,不是整数。写 0755 没问题,但写 755(十进制)会错成权限 01143,导致目录不可遍历。
- 推荐统一用
0o755(带0o前缀),语义清晰且 Go 1.13+ 明确支持 - Linux/macOS 下实际权限受
umask影响,比如umask=0027时传0o755得到的是0o750;生产环境别依赖“全开”,显式设0o755即可 - Windows 忽略权限位,但跨平台代码仍应保持一致写法,避免混淆
并发调用 os.MkdirAll 安不安全
不安全。多个 goroutine 同时执行 os.MkdirAll("a/b/c", 0o755) 可能触发竞态:系统调用重复、中间目录权限被覆盖、甚至返回 os.IsPermission(err) 等非预期错误。
立即学习“go语言免费学习笔记(深入)”;
- 高并发场景下,建议加一层同步控制(如
sync.Once或全局 map +sync.RWMutex缓存已确认存在的路径) - 更轻量的做法:先
os.Stat检查路径是否存在,存在则跳过;否则再调os.MkdirAll,并容忍os.IsExist(err) - 路径层级越深、磁盘响应越慢,竞态概率越高;日志/缓存初始化这类一次性操作,通常只需在程序启动时单次调用
最易被忽略的是权限字面量写法和并发行为——755 和 0o755 看似只差两个字符,却会导致目录无法 cd 进入;而多个 goroutine 同时创建同一路径,表面成功,实则埋下权限或竞态隐患。


















