go.mod 和 go.sum 必须一起提交,缺一不可;go.mod 声明依赖版本,go.sum 校验模块内容完整性,二者协同保障构建可重复性与安全性,单独提交 go.mod 会导致 checksum mismatch 或 ci 失败。

go.mod 和 go.sum 必须一起提交,缺一不可
很多人只提交 go.mod,认为版本号写清楚就够了,结果 CI 构建失败或本地 go build 报 checksum mismatch。这是因为 go.sum 不是可选文件——它记录每个模块内容的 SHA256 哈希,go mod verify 和构建时都会校验它。
-
go.sum被删或未提交 → 构建时会重新生成,但哈希值可能与他人环境不一致,导致go mod verify失败 -
go.sum被手动编辑(比如删掉某行)→go mod verify直接退出码 1,CI 流水线中断 - 子模块(如
./shared)也有自己的go.mod和go.sum,必须各自提交,不能只管主模块
正确做法:所有 go.mod 和对应 go.sum 都纳入 Git 跟踪;每次 go mod tidy 后,连同这两个文件一起 git add。
GO111MODULE=on 和 GOPROXY 必须硬编码到环境变量
混合局域网里,PowerShell、zsh、bash、VS Code 终端加载的 shell 配置不同,go env 输出可能不一致。有人 go build 成功,换终端就报 no required module provides package,根源常是 GO111MODULE 实际为 auto 或 off。
- 执行
go env -w GO111MODULE=on强制启用模块模式,避免 fallback 到 GOPATH - 执行
go env -w GOPROXY=https://goproxy.cn,direct,禁用默认proxy.golang.org,防止某台机器因 DNS 或防火墙阻塞 - Windows 用户注意:PowerShell 的
$env:GOPROXY设置不会被 WSL2 继承,需在 WSL 内单独运行go env -w
验证方式:go env GO111MODULE GOPROXY 输出应稳定为 on 和 https://goproxy.cn,direct,否则别跑 go build。
replace 指令只用于开发,CI 中必须失效
replace github.com/yourorg/lib => ./lib 是本地联调利器,但若漏删,CI 构建会直接失败——因为 ./lib 路径在远程 runner 上不存在。
- CI 环境应加
GOFLAGS="-mod=readonly",让任何replace或go get修改go.mod的操作立即报错 - 本地开发用
replace,发布前必须删掉,并用go mod tidy补全真实版本依赖 - 如果子模块尚未打 tag,可用伪版本(如
v0.0.0-20260804152233-abcdef123456)替代replace,既可构建又不破坏 CI
一个容易忽略的点:go list -m all 输出中带 => 的行,就是生效的 replace,上线前务必清空。
go.version 文件 + CI 校验是防版本漂移的最后防线
Go 小版本升级(如 1.21.9 → 1.21.10)可能改变 MVS 算法行为或模块解析逻辑,导致 go.sum 变动、间接依赖版本偏移。仅靠 go mod tidy 无法拦截这种隐性不一致。
- 项目根目录放纯文本文件
go.version,内容为1.21.10(不带v) - CI 脚本开头加:
[[ "$(go version | cut -d' ' -f3 | tr -d 'go')" == "$(cat go.version)" ]] || exit 1 - 本地 pre-commit hook 也可加同样检查,避免开发者用错 Go 版本提交
真正麻烦的不是版本号不匹配,而是不同 Go 版本对同一 go.mod 解析出不同 go.sum —— 这种差异往往要等到发布后才暴露,所以提前卡死版本比事后 debug 更省力。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











