1223 字
约 4 分钟
5
S09-A01 · 模块与依赖:`go.mod`、GOPROXY 与可复现构建
2024-12-31
2026-11-07

适用读者: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. 自检

  1. go.mod、go.sum、GOPROXY 各解决什么?
  2. go get 卡住的三段排查顺序?
  3. GOPRIVATE 的作用?不设会怎样?
  4. vendor 模式的收益与代价?
  5. 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/
作者
clxstart
发布于
2024-12-31
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。