os.Mkdir 只能创建单层目录且父目录必须存在,否则报错;os.MkdirAll 递归创建所有缺失目录,已存在时静默成功,是绝大多数场景的首选。

os.Mkdir 只能创建单层目录,父目录不存在会报错
调用 os.Mkdir 时,如果指定路径中的上级目录(如 /tmp/a/b 中的 /tmp/a)不存在,函数会直接返回 no such file or directory 错误。它不会自动创建中间路径,这是和 mkdir -p 的关键区别。
- 只适用于确保父目录已存在时的“最后一层”创建场景
- 权限参数
perm仅控制新建目录本身的权限位(如0755),不改变父目录权限 - 若目标路径已存在且是目录,
os.Mkdir仍会返回file exists错误(不是成功)
os.MkdirAll 是更安全的替代方案
绝大多数实际场景应优先使用 os.MkdirAll:它会递归创建所有缺失的父目录,并在目标目录已存在时静默成功(不报错)。
- 行为接近 shell 的
mkdir -p - 同样接受
perm参数,但该权限仅应用于**最深层新建的目录**;中间路径使用系统默认 umask 衍生权限(通常为0755) - 返回
nil表示路径已存在或成功创建;非nil错误才需处理
err := os.MkdirAll("/tmp/a/b/c", 0755)
if err != nil {
log.Fatal(err) // 仅当磁盘满、权限不足等真正失败时触发
}
权限参数 perm 的实际作用范围容易误解
perm 不是“最终目录权限”,而是传给底层 mkdir(2) 系统调用的 mode 值,受进程 umask 影响。例如进程 umask 为 0022,即使传入 0777,实际创建的目录权限也是 0755。
- 若需精确控制权限,应在
os.MkdirAll后用os.Chmod显式设置 - 临时绕过 umask:先
umask(0)(需 cgo 或 syscall,不推荐) - 常见写法:用
0755而非0777,避免过度开放
Windows 下路径分隔符和权限处理差异
在 Windows 上,os.MkdirAll("C:\a\b", 0755) 因反斜杠转义问题会失败。必须用正斜杠或双反斜杠:
立即学习“go语言免费学习笔记(深入)”;
- 推荐写法:
"C:/a/b"或`C:\\a\\b` - Windows 忽略
perm参数(除只读标志外),0755和0600效果相同 - 若需跨平台,用
filepath.Join("C:", "a", "b")构造路径
path := filepath.Join("tmp", "data", "logs")
err := os.MkdirAll(path, 0755) // 自动适配 / 或 \
实际项目中,几乎不需要直接调用 os.Mkdir;os.MkdirAll 覆盖了 99% 的需求,而它的错误语义更清晰、行为更可预测。唯一需要 os.Mkdir 的场景,是明确要拒绝父目录自动创建——比如校验配置路径是否严格按预期结构存在。










