go build 缓存需用 go clean -cache 清 $gocache,但对 cgo\_enabled 切换、goos/goarch 变更等场景需手动清理;go clean -modcache 清 $gomodcache 模块缓存;go clean -i 仅清理当前目录 main 包安装的二进制。

Go build 缓存怎么清,为什么 go clean -cache 有时没用
Go 的编译缓存($GOCACHE)默认启用,缓存的是编译中间产物(如 .a 文件),能大幅加速重复构建。但缓存可能 stale——比如你改了 Cgo 代码、切换了 CGO_ENABLED、或升级了 Go 版本后旧缓存未自动失效。
直接运行 go clean -cache 是最常用做法,但它只清 $GOCACHE,不碰 $GOPATH/pkg 或模块下载缓存。如果你遇到「改了代码却没生效」「go build 报错说找不到符号但明明存在」,大概率是缓存混杂了不同构建模式的产物。
-
go clean -cache清的是$GOCACHE(通常为$HOME/Library/Caches/go-buildmacOS /%LOCALAPPDATA%\go-buildWindows /$HOME/.cache/go-buildLinux) - 如果用了
CGO_ENABLED=0构建过,再切回CGO_ENABLED=1,必须清缓存,否则链接阶段可能静默失败 - Go 1.21+ 对
GOOS/GOARCH变更更敏感,但旧缓存不会自动作废,手动清更稳妥
Go mod 依赖缓存存在哪,go clean -modcache 清什么
模块依赖缓存($GOMODCACHE)存放所有 go get 下载的模块 zip 和解压后的源码,默认路径是 $GOPATH/pkg/mod。它和 go.sum 绑定,但不校验内容一致性——也就是说,如果本地模块被意外修改(比如手改了 vendor 或直接编辑了 pkg/mod 里的文件),go build 仍会照常用,直到下次 go mod download 覆盖。
go clean -modcache 会彻底删除整个 $GOMODCACHE 目录,下次构建时重新下载所有依赖。这不是日常操作,只在以下情况需要:
立即学习“go语言免费学习笔记(深入)”;
- 怀疑某个模块 zip 损坏(比如
go mod verify失败但go.sum没报错) - 切换了私有模块代理(如从
proxy.golang.org切到自建GOPROXY),旧缓存里混着不同来源的同版本模块 - CI 环境中避免跨构建污染,每次跑前加
go clean -modcache(注意:这会让首次构建变慢)
为什么 go clean -i 不总能删掉已安装的二进制
go clean -i 本意是清理通过 go install 安装到 $GOPATH/bin 或 $GOBIN 的可执行文件及其关联的安装缓存(即 $GOPATH/pkg 下的 .a 文件)。但它有个关键限制:只清理「由当前目录下 main 包安装的二进制」。
比如你在 ~/proj/cmd/mytool 执行 go install,生成了 $GOBIN/mytool;然后 cd 到 ~/proj 再执行 go clean -i,它不会删 mytool——因为当前目录没有 main 包。
- 想确保删干净,cd 进每个
cmd/xxx目录单独执行go clean -i - 更简单粗暴的做法:
rm $(go env GOPATH)/bin/*或rm $(go env GOBIN)/*(注意别误删其他工具) -
go install在 Go 1.21+ 默认使用模块缓存构建,不再写入$GOPATH/pkg,所以-i对现代工作流影响变小
CI/CD 中要不要清缓存,哪些该清、哪些不该碰
CI 流水线里缓存策略直接影响构建速度和可靠性。不是所有缓存都适合复用:模块缓存(modcache)可以安全复用,但构建缓存(build cache)跨平台/跨 Go 版本时容易出问题。
- 推荐保留
$GOMODCACHE并设为 CI 缓存项(key 可基于go.modhash),节省下载时间 -
$GOCACHE建议按GOOS/GOARCH/Go version分维度缓存,否则 macOS 上缓存的产物可能被 Linux job 错误加载 - 绝对不要复用
$GOPATH/pkg(尤其在GO111MODULE=off旧项目中),它和GOPATH强绑定,混用会导致import not found - Docker 构建中,把
go clean -cache放在go build前反而可能变慢——除非你明确知道上一次构建参数变了
缓存真正难处理的点不在「怎么清」,而在「清完之后,哪个环节会因缺失缓存而暴露原本被掩盖的问题」——比如本地能过 CI 过不了,八成是某处隐式依赖了未提交的 go.sum 变更或私有模块权限配置。










