必须一起提交go.mod和go.sum,缺一不可;二者共同锁定依赖版本与校验和,缺失go.sum会导致CI校验失败、本地与远程构建不一致。

go.mod 和 go.sum 必须一起提交,缺一不可
本地能跑、CI 报错,90% 是因为 go.sum 没提交,或提交了但被 .gitignore 误删。Go 构建时会校验每个依赖模块的哈希值,go.sum 就是这份“指纹清单”。如果缺失,Go 会尝试重新计算并写入新哈希——但网络环境、代理配置、模块镜像源差异都会导致生成的哈希不一致。
常见错误现象:go build 在本地成功,CI 报错 verifying github.com/xxx@v1.2.3: checksum mismatch;或者 go mod download 卡住不动,实际是校验失败后反复重试。
-
go.sum文件必须和go.mod同时纳入 Git 跟踪,且不能放在.gitignore里 - 团队应禁用所有 IDE 的 “auto-remove unused dependencies” 功能,这类操作常悄悄删掉
go.sum中的行 - 执行
go mod tidy后,务必检查go.sum是否有新增/删减行,并一并提交
GO111MODULE=on 不能靠环境默认,必须显式启用
Go 1.16+ 虽默认开启模块模式,但只要当前目录没 go.mod 或环境变量 GO111MODULE 未设为 on,Go 仍可能 fallback 到 GOPATH 模式——这时 go get 会把包装进 $GOPATH/src,go build 行为完全失控,本地和 CI 构建路径、依赖来源都不同。
使用场景:CI 脚本、Docker 构建、远程开发容器(如 VS Code Dev Container)中,shell 初始化脚本往往未加载,GO111MODULE 值为空。
- 所有构建命令前加
GO111MODULE=on go build,不要依赖 shell 环境变量 - 在
.zshrc或.bashrc中显式写export GO111MODULE=on,而非只靠 Go 版本“自动生效” - 检查现有项目:运行
go env GO111MODULE,输出必须是on;若为空或auto,说明配置未生效
GOPROXY 和 GOSUMDB 必须统一配置,且不能只靠本地设置
不同机器上 GOPROXY 值不同(比如本地用 https://goproxy.cn,CI 用 https://proxy.golang.org),会导致同一模块下载路径不同、校验和不一致,甚至因镜像同步延迟拉到不同 commit 的 tag。
容易踩的坑:开发者在自己机器上 go env -w GOPROXY=...,但这个设置不会进 Git,也不会进 Docker 容器或 CI runner;更糟的是,go env -w 会写入 $HOME/go/env,在多用户服务器上可能被其他用户覆盖。
- CI/CD 脚本中显式设置:例如 GitHub Actions 用
env: GOPROXY: https://goproxy.cn,direct - Docker 构建时,在
Dockerfile中ENV GOPROXY=https://goproxy.cn,direct,而非依赖基础镜像默认值 - VS Code Remote-Containers 场景下,在
.devcontainer/devcontainer.json的remoteEnv字段中声明,否则容器内go mod download会走直连,超时或失败
go version 声明要精确到 patch 版本,且所有环节必须对齐
Go 1.21.5 和 1.21.6 看似小版本升级,但可能引入模块解析逻辑变更(如 go list -m all 输出顺序)、go.sum 校验算法微调,甚至影响 replace 规则行为。CI 镜像用 golang:1.21,而本地用 asdf install golang 1.21.8,两者实际行为已不同。
性能影响:不同 Go 版本的 go mod download 并发策略、缓存命中率、TLS 握手行为均有差异,会导致构建耗时波动,间接暴露一致性问题。
- 项目根目录放
.tool-versions,内容为golang 1.21.8(精确 patch) - CI 配置中锁定镜像标签:用
FROM golang:1.21.8-alpine,不用:1.21或:latest - Docker 构建阶段避免
RUN go get -d -v .:该命令绕过go.sum校验,且 Go 1.21+ 已弃用,应改用COPY go.mod go.sum . && RUN go mod download
go mod graph、每一行 go.sum 校验、每一个 go list -m 输出,在 Windows 开发机、Linux CI runner、macOS 代码审查者机器上,字节级完全相同——这要求所有配置可声明、可透传、不可被隐式覆盖。

















