模块缓存($gomodcache)和编译缓存($gocache)是两套完全独立的系统,存放位置、作用对象、触发时机、清理方式均不同;go clean -modcache 清 $gomodcache 下全部模块源码及校验数据,不碰 go.mod/go.sum 和 $gocache;go clean -cache 仅删 $gocache 中过期 .a 文件,非全量清除,设 gocache=off 则无效。

模块缓存($GOMODCACHE)和编译缓存($GOCACHE)是两套完全独立的系统
它们存放位置、作用对象、触发时机、清理方式都不同,混用或误删会导致奇怪问题。比如你 go clean -modcache 后构建变慢,是因为源码要重下;而 go clean -cache 后构建变慢,是因为 .a 文件要重编。两者不互相依赖,也不共享数据。
常见错误现象:
-
go build速度突然变快或变慢,但没改代码 → 很可能是$GOCACHE命中或失效 -
go mod tidy没反应,或提示版本不匹配 → 多半是$GOMODCACHE里残留了损坏的 .zip 或 .info 文件 - 改了
server.go却 still undefined: MyFunc → 不是模块缓存问题,而是$GOCACHE里还存着旧的 .a,或你用了go build main.go这种孤立编译方式
go clean -modcache 清的是什么,不是什么
它清的是 $GOMODCACHE(默认为 $GOPATH/pkg/mod)下的全部内容:解压后的源码目录、cache/download/ 里的 .zip/.mod/.info、符号链接、校验数据。但它不会碰:
-
go.mod和go.sum文件(这些在项目目录里,不受影响) -
$GOCACHE(编译中间产物,得用go clean -cache单独清) -
$GOPATH/src下手动 clone 的项目(那是旧 GOPATH 模式,和模块无关) - 本地
replace指向的路径(软链接会被删,但go mod edit -replace记录还在)
执行后首次 go mod download 或 go build 会重新拉取所有依赖,耗时明显增加——这是正常表现,不是失败。
go clean -cache 不等于彻底删除 $GOCACHE
这个命令只清理“过期”条目,比如被标记为 stale 的 .a 文件,或者哈希不匹配的 action 缓存。它不会清空整个目录,也不会删掉未过期但你主观认为“该删”的东西。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
想真正清空编译缓存,得用:
rm -rf $(go env GOCACHE)/*
注意末尾的 /* ——漏掉就可能误删父目录。另外:
- 如果设置了
GOCACHE=off,go clean -cache什么都不会做 - 切换
CGO_ENABLED、GOOS、GOARCH后,旧缓存大概率不生效,但不会自动清理,必须手动干预 -
go test -count=1是否快,直接受$GOCACHE影响;而go test -count=2第二次快,是因为命中了缓存
为什么 go mod verify 有时失败,但 go build 却能过
因为 go mod verify 严格比对 go.sum 里的 checksum 和 $GOMODCACHE 中对应版本的 .info 文件;而 go build 默认跳过这一步,只要源码目录存在就直接用。
这意味着:
- 你手动改过
$GOMODCACHE/github.com/user/repo@v1.2.3/里的文件,go mod verify一定报错,但go build可能照常通过 -
go.sum没提交进 Git,不同人本地缓存可能各自校验通过,但内容实际不一致 - 磁盘写入中断导致
.zip下载不全,.info里记录的 checksum 就和实际解压内容对不上 → 这是go mod verify失败最常见原因
真正需要厘清的,不是“缓存该不该清”,而是“哪个缓存出了问题”。看报错信息里带不带 checksum mismatch、cannot find module、undefined symbol,就能快速定位到 $GOMODCACHE、$GOCACHE 还是构建路径本身的问题。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










