Go module cache 默认存于 $GOPATH/pkg/mod(Go 1.13+ 为 $HOME/go/pkg/mod),由所有本地 Go 项目共用,go mod download、go build、go test 等命令均依赖它查源码并软链接使用;缓存路径通过 go env GOMODCACHE 确认,清理须用 go clean -modcache。

Go module cache 存在哪、谁在用它
Go 的模块缓存不是临时目录,而是全局复用的持久存储,默认放在 $GOPATH/pkg/mod(Go 1.13+ 默认 $HOME/go/pkg/mod)。所有本地项目只要用 go mod download 或执行 go build、go test 等命令,都会先查这个目录——命中就跳过下载,直接软链接进当前项目的 vendor 或构建缓存。
注意:go mod tidy 和 go get 同样依赖它;但如果你删了 go.sum 又没清缓存,go build 可能成功,而 go mod verify 会失败——因为缓存里存的是原始 zip 解压后的源码,校验和只在 go.sum 里。
- 缓存路径可通过
go env GOCACHE和go env GOPATH确认,GOCACHE是编译产物缓存,GOPATH/pkg/mod才是模块源码缓存 -
go clean -modcache会彻底清空它,慎用;日常调试建议用go list -m all配合go mod download -json查看模块是否已缓存 - 多项目共用同一缓存,但不同 Go 版本(如 1.21 vs 1.22)的
go.mod语义解析可能不同,缓存内容不跨版本兼容
为什么 go mod download 有时不生效
常见现象:明明改了 go.mod 里的版本号,执行 go mod download 却没更新缓存。根本原因是 Go 不会覆盖已有模块版本——哪怕你把 github.com/foo/bar v1.2.3 改成 v1.2.4,只要 v1.2.3 还在缓存里,go mod download 就不会碰 v1.2.4,除非它真被引用到依赖图中。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
- 触发下载的条件是「该模块版本被当前
go.mod显式声明或间接依赖」,而不是「出现在go.mod文件里」 - 用
go mod graph | grep foo可确认某模块是否实际参与依赖解析 - 若想强制刷新某个模块,先
go clean -modcache再go mod tidy;更轻量的做法是删掉$GOPATH/pkg/mod/cache/download/github.com/foo/bar/@v/v1.2.4.info和对应.zip,再运行go mod download github.com/foo/bar@v1.2.4
离线构建时如何确保缓存完整
单机环境做离线构建,不能只靠 go mod vendor。vendor 目录只包含直接/间接依赖的源码快照,但 Go 构建过程仍会读取 $GOPATH/pkg/mod 中的元数据(比如 .info、.lock 文件)来验证 checksum 和版本一致性。
立即学习“go语言免费学习笔记(深入)”;
- 推荐做法:在线时先
go mod download全量拉取,再用go mod verify检查完整性;离线前备份整个$GOPATH/pkg/mod目录 - 若仅复制 vendor,需额外运行
go mod edit -replace把所有远程路径映射为本地路径(如-replace=github.com/x/y=./vendor/github.com/x/y),否则go build仍会尝试联网解析 -
GOFLAGS="-mod=vendor"可强制使用 vendor,但它不解决 checksum 校验缺失问题;真正可靠的离线方式是保留完整pkg/mod并设置GOPATH指向该离线路径
缓存污染导致构建不一致的典型场景
最隐蔽的问题是:同一 commit,在 A 机器上构建成功,B 机器上失败,错误常是 cannot load ...: module ...@version found, but does not contain package ...。这往往不是代码问题,而是 B 机器的模块缓存里混入了被篡改或不完整解压的版本。
- 常见诱因:手动修改
$GOPATH/pkg/mod下某模块源码、磁盘损坏导致 zip 解压中断、CI 机器共享 NFS 缓存但未加锁 - 验证方法:对比两台机器上
go list -m -f '{{.Dir}}' github.com/foo/bar@v1.2.3返回的路径,再检查该路径下是否有go.mod和预期包文件 - 修复不是删缓存那么简单——得确认
go.sum里该模块的 hash 是否匹配官方 checksum(可用go mod download -json github.com/foo/bar@v1.2.3获取官方 hash),不匹配就得清缓存重拉

















