最稳妥高效的go缓存策略是直接缓存$gomodcache路径并以go.sum哈希为key;不应缓存vendor/目录,因其引发权限问题、环境漂移且冗余;需设go111module=on并合理配置goproxy。

直接缓存 GOMODCACHE 路径 + 用 go.sum 哈希做 key,是最稳妥、最高效的做法。别缓存 vendor/ 目录,也别只用分支名当 key。
为什么不能缓存 vendor/ 目录?
缓存 vendor/ 看似直观,但实际会引入权限问题(CI 容器用户 UID 不一致)、环境漂移(不同 Go 版本生成的 vendor 内容不完全兼容),且 go mod vendor 本身是冗余操作——Go 模块机制已原生支持离线构建,vendor/ 只在极少数合规场景才需提交。
- 每次
go mod vendor都会重写整个目录,哪怕只改一行go.mod,缓存就全失效 -
vendor/包含项目特定的 autoloader 和脚本,和构建环境强耦合 - GitLab CI 默认不保留文件所有权,解压后权限常为 root:root,导致后续
go build失败
应该缓存什么?怎么设 cache key?
Go 的模块下载缓存默认存在 $GOMODCACHE(通常是 $HOME/go/pkg/mod),里面只存校验过的 zip 包和元数据,不依赖具体项目结构,天然适合跨 job 复用。
Go语言(Golang)1.26.0版本提供 Go 官方 Windows amd64 MSI 安装包下载入口,版本号 1.26.0,可用于旧项目维护、兼容性测试和指定版本开发环境配置。
- 缓存路径必须写成
paths: - $GOMODCACHE,不能写死绝对路径(如/root/go/pkg/mod),否则在不同 runner 上失效 - key 推荐用
files:方式,基于go.sum内容哈希:cache:<br> key:<br> files:<br> - go.sum<br> paths:<br> - $GOMODCACHE
- 如果项目有多个
go.sum(如子模块),可加- **/go.sum,但注意 GitLab 会按字典序拼接哈希,顺序要稳定
构建时必须显式启用模块模式
CI 环境里 Go 默认可能 fallback 到 GOPATH 模式,尤其旧版 runner 或自定义镜像。必须确保 GO111MODULE=on 且 GOPROXY 设置合理。
- 在
before_script或 job-levelvariables中声明:variables:<br> GO111MODULE: "on"<br> GOPROXY: "https://proxy.golang.org,direct"
- 避免在 script 中反复执行
go mod download——go build或go test会自动触发依赖解析,只要go.sum在、GOMODCACHE缓存命中,就跳过网络请求 - 若用私有模块,
GOPROXY应配企业代理(如 Athens)并确保 runner 能访问,否则缓存无意义
多模块项目要注意 replace 和本地路径
当项目含 replace 指向本地路径(如 replace example.com/lib => ../lib),go.sum 不会记录该路径内容哈希,缓存 key 就无法感知变更,容易构建不一致。
- CI 中应避免
replace指向相对路径;改用 git tag + 语义化版本,或通过GIT_SSH_COMMAND让 Go 模块能拉取私有 repo - 若必须用本地 replace,需在 cache key 中额外加入对应目录的哈希:
key:<br> files:<br> - go.sum<br> - ../lib/go.mod
-
go mod graph可验证 replace 是否生效,CI 脚本里加一句能早发现问题
真正卡住构建速度的,往往不是下载慢,而是缓存没命中或命中了错误的内容。go.sum 是事实来源,GOMODCACHE 是唯一可信缓存位置——其他路径都是临时工,不该被信任。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










