1223 字
约 4 分钟
5
S09-A01 · 模块与依赖:`go.mod`、GOPROXY 与可复现构建
适用读者:
go mod tidy卡住、或要保证团队构建一致的人。
前置:S09-B01。
实测环境:Go 1.22.2;go mod行为与GOPROXY配置为实测,模块代理的可用性随网络变化。
覆盖旧文:A-1471(go get没反应,17 点)。
覆盖扩展:E-S09-012(GOPROXY 链路)、E-S09-013(vendor 模式)。
上一篇:S09-J03 · 闭包与捕获:从 1.21 到 1.22 的语义变更
下一篇:S09-A02 · 语言选型 ADR。
1. 一句话结论
Go 的可复现构建由三个文件保证:go.mod(要什么)、go.sum(是不是这个东西)、GOPROXY(从哪拿)。
| 文件/配置 | 作用 | 缺失后果 |
|---|---|---|
go.mod |
模块路径 + 依赖版本 | 无法构建 |
go.sum |
依赖的内容哈希 | 无法验证"拿到的包没被替换" |
GOPROXY |
模块代理地址 | 拉不到(网络受限时) |
GOMODCACHE |
本地缓存 | 每次重新下载 |
2. 实测:基本命令
$ go mod init lab
$ cat go.mod
module lab
go 1.22
$ go env GOPROXY GOMODCACHE GOFLAGS
https://proxy.golang.org,direct
/root/go/pkg/mod
| 命令 | 作用 |
|---|---|
go mod init <path> |
初始化模块 |
go mod tidy |
增删依赖,使 go.mod/go.sum 与实际 import 一致 |
go mod download |
只下载依赖到缓存 |
go mod verify |
校验缓存中的依赖是否与 go.sum 一致 |
go list -m all |
列出最终生效的依赖版本 |
3. 拉不到包的三段排查(E-S09-012)
go: downloading … 卡住 / 报错
│
① 网络层:能不能到达代理?
│ curl -I https://proxy.golang.org (或你的私有代理)
↓
② 代理配置层:GOPROXY 是否设置了可用的代理?
│ go env GOPROXY
│ → 国内常设为 https://goproxy.cn,direct
↓
③ 校验层:GOFLAGS / GONOSUMDB / GOPRIVATE 是否与私有仓库冲突?
go env GOPRIVATE GONOSUMDB GONOSUMCHECK
旧文 A-1471 的痛点(go get 没反应)正是第 ② 层:默认 proxy.golang.org 在国内常不可达。
# 常见修法
go env -w GOPROXY=https://goproxy.cn,direct
# 私有仓库不走公共代理、也不做校验
go env -w GOPRIVATE=git.example.com
| 变量 | 作用 |
|---|---|
GOPROXY |
代理链,direct 表示回退到直连 |
GOPRIVATE |
匹配的模块不走公共代理、不上传校验库 |
GONOSUMDB / GONOSUMCHECK |
兼容旧名(现多用 GONOSUMDB/GOPRIVATE) |
GOSUMDB |
校验数据库(默认 sum.golang.org) |
4. 可复现的三件套(E-S09-013)
| 要素 | 做法 |
|---|---|
| 版本锁定 | go.mod 里精确版本(Go 的 MVS 会自动选最小满足版本) |
| 内容校验 | 提交 go.sum(必做,不要 gitignore) |
| 构建一致性 | CI 与本地同一个 Go 版本(go.mod 的 go 指令 + CI setup-go) |
| 离线/内网构建 | vendor 模式:go mod vendor + -mod=vendor |
$ go mod vendor # 把依赖复制到 vendor/
$ go build -mod=vendor # 只用 vendor,不访问网络
| 模式 | 优点 | 代价 |
|---|---|---|
| 默认(module cache) | 简单 | 依赖网络/缓存 |
| vendor | 完全离线、可审计 | 仓库体积变大、更新需重新 vendor |
判据:内网/审计要求 → vendor;公网 CI → 默认 + go.sum。
5. go.sum 到底保证什么
| 它保证 | 它不保证 |
|---|---|
| 下载到的模块内容与记录一致 | 模块内容本身"安全"(没有恶意代码) |
| 依赖未被中间人替换 | 作者是否可信 |
| 不同机器拿到同一份代码 | 构建产物完全一致(还受 Go 版本/编译参数影响) |
所以 go.sum 是"完整性",不是"安全性"——签名/来源可信要靠别的手段(与 S01-A02 的供应链治理同源)。
6. 五个误区
| 误区 | 真相 |
|---|---|
"go.sum 可以 gitignore" |
必须提交,否则无法验证 |
"go get 卡住是网络坏了" |
多半是 GOPROXY 不可达(§3) |
| "私有仓库也能走公共代理" | 需要 GOPRIVATE 排除 |
| "vendor 模式更先进" | 是权衡:换离线,付体积 |
"go.sum 能防恶意代码" |
只防替换,不防作者 |
7. 自检
go.mod、go.sum、GOPROXY各解决什么?go get卡住的三段排查顺序?GOPRIVATE的作用?不设会怎样?- vendor 模式的收益与代价?
go.sum为什么防不了恶意代码?
8. 下一篇
S09-A02 · 语言选型 ADR:Go vs Java vs Python
依赖治理讲完,最后一篇做语言级选型:按什么维度选、什么情况 Go 不合适、ADR 怎么写。
本篇属于系列《S09 · Go 语言》,架构师层第 1 篇。旧文来源:A-1471;扩展点 E-S09-012/013。go env/go mod 行为为 Go 1.22.2 实测。
S09-A01 · 模块与依赖:`go.mod`、GOPROXY 与可复现构建
https://www.clxhxhhr.top/posts/5311/ 评论
0 条
还没有评论,先写一条吧。