应校验路径合法性后再用os.RemoveAll删除临时目录,禁止危险路径如"../";定期清理时间戳目录需用os.ReadDir筛选并严格校验;大目录删除宜用filepath.WalkDir分步处理;模块缓存需go clean -modcache而非os.RemoveAll。

用 os.RemoveAll 清理已知路径的临时目录,但必须校验路径合法性
直接删整个目录最快,但风险也最高。比如你想清理 ./dist 或 ./tmp,os.RemoveAll("./dist") 能一步到位,但它不检查你传进去的字符串是不是拼错了——os.RemoveAll("../") 在有权限时真会删上级目录。
实操建议:
- 所有路径先做白名单校验:只允许以
"./"开头,且不含".."、"//"、"~/"等危险片段 - 删除前加一层
os.Stat检查路径是否存在,避免误把错误路径当空操作跳过 - 生产环境建议加日志记录:删了什么、谁触发的、是否成功,方便事后追溯
- CI/CD 中可配合
set -e和pwd输出当前工作目录,防止相对路径错位
按规则筛选并删除过期子目录,别硬编码 ioutil.ReadDir
很多项目需要定期清理形如 20250601123456 这类时间戳命名的构建产物目录,这时候不能靠 os.RemoveAll 一把梭,得先识别再删。
注意点:
立即学习“go语言免费学习笔记(深入)”;
-
ioutil.ReadDir已被弃用,改用os.ReadDir(Go 1.16+),它不走os.Stat,性能更好 - 判断是否为目录要用
entry.IsDir(),别依赖名字后缀或字符串匹配 - 时间戳校验要严格:长度、数字范围、是否能解析成
time.Time,否则可能误删20250x01xxxx这种非法值 - 保留列表(如
["20250610", "latest"])建议从配置文件读,别写死在代码里
递归删除大目录时卡住?换 filepath.WalkDir + 手动队列
os.RemoveAll 在删几万个小文件或深层嵌套目录时,可能阻塞主线程甚至超时。这不是 bug,是它的设计使然——它同步递归,不提供进度反馈或中断能力。
替代方案的核心是分两步走:
- 用
filepath.WalkDir遍历所有路径,只收集文件(entry.Type().IsRegular()),跳过目录 - 把所有文件路径塞进
container/list.List,倒序遍历调用os.Remove(先删文件,再删空目录) - 最后再单独处理目录路径(按深度降序),对每个目录调用
os.Remove;失败说明还有残留或权限问题 - 每个
os.Remove都要检查os.IsNotExist和os.IsPermission,Windows 上遇到syscall.EBUSY可重试一次
删完发现模块还在磁盘上?go clean -modcache 是另一回事
项目目录下的无效文件和模块缓存是两码事。go mod tidy 只改 go.mod 和 go.sum,删的是“声明”;而 $GOPATH/pkg/mod 里的下载包,哪怕项目里一个都没引用,也会一直占着磁盘。
真正释放空间得靠:
-
go clean -modcache:清空全部模块缓存,适合 CI 或重置环境 - 手动删
$GOPATH/pkg/mod/cache/download下某模块的特定版本(如github.com/some/pkg/@v/v1.2.3.zip) - 企业级场景下,如果用了私有代理(如 Athens),本地缓存只是镜像,清理还得看代理配置
别指望 os.RemoveAll 能碰模块缓存目录——它默认不在项目目录内,路径不对就删了个寂寞。


















