go mod download 必须在构建前显式执行,否则 go build 会因缺失模块直接报错;CI/CD 中需在 cache 恢复后、go build 前运行 go mod download -x,并确保 GOPROXY 配置为 https://goproxy.cn,direct 等含 direct 的合法格式,缓存 key 应基于 go.sum 哈希,Dockerfile 中需先 COPY go.mod/go.sum 再执行下载。

go mod download 必须在构建前显式执行
CI/CD 中 go build 不会自动补全缺失模块,它直接报错退出。真正触发下载的是 go mod download 或首次遇到未缓存模块的 go list/go test —— 但此时是阻塞、单线程、不可控的。不提前拉取,等于把网络延迟和失败风险全押在构建阶段。
- 所有 CI job 开头第一行就该是
go mod download -x(-x可确认是否走代理) - GitLab CI / GitHub Actions 中,这步必须放在
cache恢复之后、go build之前 - 若项目含私有模块,
go mod download会因GOPROXY配置不当而卡住或 404,此时direct必须出现在代理链末尾
GOPROXY 配置必须带 direct 且顺序不能错
GOPROXY=https://goproxy.cn 单独设置是危险的:它会把所有模块(包括 git.internal.company/project)都转发给代理,而国内镜像无法解析内网域名,结果就是 module not found 或 404。
- 正确写法是
GOPROXY=https://goproxy.cn,direct——direct是关键字,不是字符串,必须小写、无空格、在末尾 - 验证方式:
go env GOPROXY输出应严格为https://goproxy.cn,direct - 如果用了私有代理(如 JFrog Artifactory Go repo),也得写成
GOPROXY=https://artifactory.example.com/artifactory/api/go/gocenter,direct
CI 缓存 key 必须基于 go.sum 哈希
只缓存 $HOME/go/pkg/mod 目录不够,key 若不绑定依赖内容,go.mod 小改(比如升级一个 patch 版本)就会命中旧缓存,导致构建用错版本、行为不一致。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- GitHub Actions 推荐 key:
cache-go-mod-${{ hashFiles('**/go.sum') }} - GitLab CI 可用:
cache-go-mod-${CI_COMMIT_TAG:-$CI_COMMIT_SHORT_SHA},但不如哈希可靠;更稳妥是脚本生成sha256sum go.sum | cut -d' ' -f1 - 切勿缓存整个
$HOME/go—— 它含GOPATH下的构建产物,可能污染后续 job
Docker 构建中依赖层必须独立且前置
Dockerfile 里把 COPY . . 放在 go mod download 前面,会导致每次代码变更都让依赖层失效,彻底失去缓存价值。
立即学习“go语言免费学习笔记(深入)”;
- 正确顺序:先
COPY go.mod go.sum .→ 立即RUN go mod download→ 再COPY . . - 务必在
.dockerignore中排除/vendor、/node_modules、**/*.md等无关文件,避免 COPY 触发误失缓存 - 多阶段构建中,build stage 的
go mod download结果不会自动带入 final stage,所以 final stage 若需运行时依赖(如 cgo 动态库),得单独处理
go.sum 不变、GOPROXY 配置稳定、且 go mod download 执行路径不被干扰 —— 这三者任一出问题,缓存就退化成摆设。

















