不能跨机器共享$gomodcache,因其内容为带校验锚点的本地快照,不同代理或git clone结果会导致.checksum不一致,引发校验失败;正确方案是统一goproxy配置并提交go.mod/go.sum。

跨机器共享 $GOMODCACHE 会导致校验失败和静默行为不一致
不能跨机器共享 $GOMODCACHE(默认为 $GOPATH/pkg/mod),这不是性能优化手段,而是引入构建不稳定性的高危操作。它的内容不是“可移植的源码包”,而是带校验锚点的本地快照:每个 @vX.Y.Z 目录下都包含一个 .info 文件,里面存着该模块 zip 解压前的 checksum —— 这个值由 go.sum 中记录的哈希决定,而 go.sum 本身受本地 GOPROXY 配置影响。
- 同一模块版本,若 A 机从
https://goproxy.cn下载、B 机从https://proxy.golang.org下载,zip 内容可能因代理实现差异(如重写 go.mod)不同,导致.info校验失败 - 私有模块走
direct时,A 机 git clone 的 commit hash 和 B 机可能不一致(比如分支 HEAD 移动了),但go mod download不会重新校验已缓存版本 - 手动修改过缓存目录里的源码?
go build仍会跳过校验直接用 —— 除非你运行go mod verify,但它只检查go.sum,不扫描缓存文件系统
为什么 rsync 或 NFS 挂载 $GOMODCACHE 是无效且危险的
同步 $GOMODCACHE 目录看似省流量,实则绕过了 Go 工具链的设计契约:模块缓存的“有效性”不由文件存在性决定,而由三重校验链保障(go.sum → .info → 实际 zip 内容)。NFS 或 rsync 只复制字节,不重建校验上下文。
- NFS 上并发
go mod download可能损坏download/子目录下的.mod或.zip文件(写入未完成就被其他进程读取) - rsync 后若某台机器的
GOPROXY配置变更(例如从direct切到代理),Go 仍会尝试复用旧缓存,但校验失败时只报checksum mismatch,不提示来源差异 -
go clean -modcache在共享路径上执行,会清掉所有人的缓存,CI 构建瞬间变慢十倍
真正可行的跨机依赖同步方案只有 GOPROXY + go.mod/go.sum
依赖一致性不靠“复制缓存”,而靠“统一下载源头”和“锁定校验指纹”。团队只需确保每台机器的 GOPROXY 指向同一个可信代理(如 https://goproxy.cn),并提交 go.mod 和 go.sum 到 Git。
- 首次
go build时,所有人从同一代理拉取相同 zip,生成一致的.info和解压源码 - 私有模块必须配置
direct在GOPROXY末尾,否则git.example.com/internal/lib会被代理拒绝,触发 fallback 失败 - CI 环境建议加一步
go mod verify,它会遍历go.sum逐个比对缓存中对应.info,失败即中断构建
别混淆 GOMODCACHE 和 GOCACHE:后者根本不能跨机
GOCACHE(构建缓存)比 GOMODCACHE 更不能共享——它存的是目标平台特定的中间对象(.a 文件),绑定 CGO_ENABLED、GOOS/GOARCH、Go 版本甚至 gcc minor 版本。把 Linux 上生成的 GOCACHE 拷到 macOS,go build 会直接报 invalid cache object 或静默跳过。
- 常见误操作:在 Docker CI 中挂载
/home/user/.cache/go-build作为 volume,结果不同 Go 版本 job 共享缓存,引发链接错误 - 正确做法:用 GitHub Actions 的
actions/cache,key 必须包含go-version和os,例如go-cache-${{ runner.os }}-${{ hashFiles('**/go.sum') }} - 本地开发无需操心
GOCACHE同步,它本就是单机加速器;跨机场景下,唯一需要同步的只有文本态的go.mod/go.sum和环境变量GOPROXY
go mod 的缓存机制本质是“分布式但强一致”,不是“集中式共享”。最易被忽略的点是:你以为在同步缓存,其实真正起作用的是 GOPROXY 配置和 go.sum 提交的时机 —— 它们共同构成信任链起点,其余都是衍生产物。golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











