os.Mkdir只创建最后一级目录,父目录必须存在;os.MkdirAll会逐级创建所有缺失的上级目录。最常见错误是误用os.Mkdir创建多级路径导致“no such file or directory”错误。

os.Mkdir 和 os.MkdirAll 的区别在哪
创建目录时最常踩的坑,是用 os.Mkdir 去建多级路径,结果报 no such file or directory。因为 os.Mkdir 只建最后一级,父目录必须已存在;而 os.MkdirAll 会逐级创建缺失的上级目录,更接近你直觉里“建个路径”的需求。
- 用
os.Mkdir:适合明确知道父目录一定存在,比如在已知的临时目录下建子目录 - 用
os.MkdirAll:绝大多数场景该用它,尤其路径来自用户输入或配置文件 - 注意权限参数:两个函数第二个参数都是
os.FileMode,比如0755,Windows 上部分位会被忽略
删除空目录用 os.Remove,非空目录用 os.RemoveAll
os.Remove 只能删空目录,删非空目录会返回 directory not empty 错误;想递归删整个目录树(含所有子文件、子目录),必须用 os.RemoveAll。
-
os.Remove也用于删文件,行为统一:只删目标本身,不处理内容 -
os.RemoveAll是“暴力清空”,不会提示、不走回收站,删完即失 - 如果只想清空目录内容但保留目录本身,得自己遍历
os.ReadDir+ 逐个os.Remove
检查目录是否存在别用 os.IsNotExist 手动判错
很多人写 if _, err := os.Stat(path); os.IsNotExist(err) 来判断目录是否存在,这容易漏掉其他错误(比如权限拒绝),而且语义绕。Golang 1.16+ 推荐直接用 os.ReadDir 或 os.Stat 后检查 os.IsNotExist,但更稳妥的是封装成一个函数:
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
func DirExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
- 不要只看
err != nil就认定不存在——可能是权限问题、磁盘故障等 -
os.Stat返回的os.FileInfo要用IsDir()方法确认是目录,不是文件 - Windows 下注意路径分隔符,
filepath.Join比硬写"\"或"/"更安全
并发操作目录时要注意什么
Go 本身不禁止并发调用 os.MkdirAll 或 os.RemoveAll,但多个 goroutine 同时对同一路径做创建/删除,结果不可控:可能重复建目录(无害)、可能删掉别人刚建好的内容、也可能因竞态导致部分子目录残留。
立即学习“go语言免费学习笔记(深入)”;
- 没有内置的目录级锁,需要自己加
sync.Mutex或用sync.Once控制初始化 - 若只是确保某个路径存在,
os.MkdirAll本身是幂等的,多次调用没问题;但和os.RemoveAll混用时就危险 - 生产环境涉及共享路径的操作,建议把目录管理逻辑收口到单个 goroutine 或服务中,避免裸奔并发
os.MkdirAll 和 os.RemoveAll 看似简单,但路径拼接、错误分类、并发边界这几个点,一不留神就埋进日志里查半天。

















