os.MkdirAll是Go中创建多级目录的唯一可靠方法,它逐级创建缺失父目录、已存在时不报错、权限需用0o755格式、路径应clean处理且不带尾斜杠。

os.MkdirAll 是 Go 里创建文件夹(含多级路径)唯一靠谱的选择,别用 os.Mkdir —— 它只建单层,路径里任何上级目录不存在就直接报错。
为什么 os.MkdirAll 是默认答案
它会逐级检查并创建缺失的父目录,比如 "a/b/c" 不存在时,自动补上 a 和 a/b;而 os.Mkdir 遇到 a/b 就卡死,报 "no such file or directory"。
- 返回值是
error,但成功时返回nil,已存在也不报错(这点和 Python 的os.makedirs(exist_ok=True)类似) - 权限参数是
os.FileMode,不是八进制字面量:写0755要加0o前缀(0o755),否则会被当成十进制 755 → 权限错乱 - Windows 下路径分隔符用
/或\都行,os.MkdirAll内部会自动适配
os.MkdirAll 的典型错误写法
常见报错:"mkdir /tmp/a/b: no such file or directory",基本等于你误用了 os.Mkdir。
- 把
os.Mkdir当成os.MkdirAll用,尤其在写工具脚本时图快硬编码单层调用 - 权限传了整数如
755,实际要0o755(Go 解析数字字面量默认十进制) - 路径末尾带斜杠,比如
"logs/",虽然多数情况能过,但某些系统或挂载点下会触发奇怪行为(建议统一不带尾部/)
真实项目中怎么安全调用
别裸调 os.MkdirAll,至少包一层错误处理逻辑。
立即学习“go语言免费学习笔记(深入)”;
- 检查返回
err是否为nil,非nil时先用os.IsExist(err)判断是不是“已存在”——这不算失败,可忽略 - 如果路径来自用户输入或配置,务必用
filepath.Clean()规范化,防止../跳出预期目录 - 日志路径、缓存目录这类高频创建场景,建议封装成函数,固定权限(如
0o755)和 clean 步骤
示例:
if err := os.MkdirAll(filepath.Clean("data/cache"), 0o755); err != nil && !os.IsExist(err) {
log.Fatal("failed to create dir:", err)
}
跨平台权限和符号链接的坑
Linux/macOS 上 0o755 表现正常;Windows 忽略权限位,但会保留字段(不影响功能)。真正容易翻车的是符号链接路径。
- 如果中间某层是软链,
os.MkdirAll默认按链接目标解析路径,不是链接本身——多数时候是你想要的,但调试时容易误判 - 想严格按路径字符串创建(比如软链名就是目录名),得自己
os.Stat+os.Lstat判断,再手动拆解路径逐级建 - 容器环境(如 Docker)里挂载的 volume 权限由宿主机控制,
os.MkdirAll设的0o755可能被覆盖,别依赖它做权限校验
路径合法性、权限字面量写法、软链语义——这三个地方不细看文档,很容易在线上跑几天才暴露问题。


















