go.sum 不锁定版本,仅校验依赖完整性;它记录各模块版本的 SHA256 哈希(h1:开头),供构建时验证代码未被篡改,实际版本由 go.mod 中的 require、GOPROXY 和本地缓存共同决定。

go.sum 文件不是锁版本的,它只校验依赖完整性
很多人误以为 go.sum 能像 package-lock.json 或 Pipfile.lock 那样锁定模块版本——其实不能。go.sum 只记录每个模块版本对应的内容哈希(h1: 开头的 SHA256),用于 go build、go test 时校验下载的代码是否被篡改或意外变更。真正决定“用哪个版本”的是 go.mod 中的 require 语句和 go get 的行为。
模块版本实际由 go.mod + GOPROXY + 本地缓存共同决定
执行 go build 时,Go 并不读取 go.sum 来选版本,而是:
- 解析
go.mod中的require,比如github.com/gin-gonic/gin v1.9.1 - 检查本地
$GOPATH/pkg/mod是否已存在该版本;若无,则通过GOPROXY(默认https://proxy.golang.org)下载 - 下载后,将模块解压到本地,并把其所有 .go 文件哈希写入
go.sum
这意味着:如果你删掉 go.sum,再运行 go build,Go 会重新下载相同版本(只要 go.mod 没变、代理没返回不同内容),并生成新的 go.sum 行——但内容应一致。若不一致,说明源已被污染或代理不可靠。
如何真正锁定依赖版本(含间接依赖)
Go 默认只在 go.mod 中显式声明直接依赖。间接依赖(transitive)版本由 Go 自动推导,可能随上游更新而变。要锁定全部依赖(包括间接的),需:
立即学习“go语言免费学习笔记(深入)”;
- 运行
go mod vendor:把所有依赖复制进vendor/目录,后续构建加-mod=vendor参数即可完全离线、确定性构建 - 或使用
go mod graph | grep+go get显式拉取关键间接依赖版本,再go mod tidy固化到go.mod - 注意:Go 1.17+ 默认启用
go.sum校验;若想跳过(仅调试),可用GOINSECURE或GOSUMDB=off,但生产环境禁止
示例:强制升级某间接依赖并锁定
go get github.com/sirupsen/logrus@v1.9.3 go mod tidy
这会让 Go 把 logrus v1.9.3 写入 go.mod(即使你没直接 import),并更新 go.sum 中对应哈希。
go.sum 常见问题与修复方法
典型报错如:verifying github.com/xxx@v1.2.3: checksum mismatch,原因通常是:
- 模块作者重写了 tag(极不推荐,但发生过)
- 你本地
go.sum记录的是旧哈希,而代理返回了新内容 - 用了非官方 proxy(如私有仓库)返回了不同 zip 包
修复方式(按安全优先级排序):
- 先确认是否真要信任新内容:
go clean -modcache清空本地缓存,再go mod download看是否仍报错 - 若确认合法变更,运行
go mod verify查看差异,然后go mod tidy -v自动更新go.sum - 极端情况(如私有模块未发布新 tag 却改了 commit),可手动编辑
go.sum替换哈希值——但必须确保来源可信
go.sum 不该手动维护,它的生成和校验是 Go 工具链自动完成的闭环。唯一需要人干预的,是当哈希不匹配时判断「该信谁」。










