go mod download卡住或oom需限并发、分批下载并配goproxy=direct和gosumdb=off;离线机报“no such host”是因未关闭代理与校验,必须显式设置二者;含cgo依赖需提前安装对应c开发库或设cgo_enabled=0。

go mod download 会卡住或 OOM,怎么办
go mod download 默认并发拉取所有模块,对内存和网络带宽敏感。资源受限主机(如 1GB RAM 的 ARM 设备、国产轻量云主机)常出现进程被 kill、卡在某个模块不动、或
runtime: out of memory 报错。
关键不是“等它跑完”,而是限制并发和缓冲行为:
- 用
-x 参数观察实际下载路径和模块顺序,确认是否卡在某个大包(如 github.com/ethereum/go-ethereum)
- 加
-v 看进度,避免误判为假死
- 强制限流:设置环境变量
GOPROXY=https://goproxy.cn,direct(国内镜像 + fallback),比默认 proxy.golang.org 更稳定
- 降低并发:Go 1.21+ 支持
GOFLAGS=-toolexec="sh -c 'ulimit -v 300000 && $*'" 控制单个工具内存上限,但更直接的是分批下载
推荐做法是先
go list -m all | head -n 50 截前 50 个模块,用
go mod download <module>@<version></version></module> 逐批执行,每批后
sleep 2 让系统回收内存。
离线机上 go mod download 报 “no such host” 不是没网,是配置漏了
即使已断网,
go mod download 仍会尝试解析
proxy.golang.org 和
sum.golang.org —— 这不是 bug,是 Go 默认行为。
必须在离线机上显式关闭两项:
-
go env -w GOPROXY=direct(不是 off 或空值;direct 表示跳过代理,直连本地缓存)
-
go env -w GOSUMDB=off(设为 off 才真正禁用校验;设为空字符串 "" 会 fallback 到默认 sum.golang.org)
如果项目含
replace 指向私有 Git 地址(如
git.internal.com/foo),还需加
-mod=readonly 启动参数,否则
go build 仍会尝试解析该域名。
依赖里含 cgo,但离线机没装 libc-dev,build 就挂
go mod download 只管 Go 源码,不检查底层 C 依赖。一旦模块用了 cgo(比如
net 包调 DNS、
sqlite3、
zlib),离线构建时就会报
cannot find -lc 或
fatal error: sys/socket.h: No such file or directory。
验证方式很简单:
go list -f '{{.CgoFiles}}' ./... 查哪些包含 C 文件。常见高危包包括:
github.com/mattn/go-sqlite3
-
golang.org/x/net(部分子包启用 cgo 后才支持系统 DNS)
github.com/godbus/dbus
应对策略分两层:
- 若允许纯 Go 回退:设
CGO_ENABLED=0,但注意 net 包将无法读 /etc/resolv.conf,DNS 解析可能失效
- 若必须用 cgo:离线机需提前装对应开发库,例如 Ubuntu/Debian 装
libc6-dev、libssl-dev;麒麟/统信系统查 apt search dev 或用 dnf provides */sys/socket.h
vendor 后 go build 仍失败,问题不在 vendor 目录本身
go mod vendor 复制源码到
vendor/,但 Go 构建时仍会读
go.sum 和
$GOPATH/pkg/mod 中的元信息。如果离线机上
go.sum 缺失、哈希不匹配,或
go.mod 里有
// indirect 依赖未被
vendor/modules.txt 覆盖,
go build 就会拒绝启动。
真正有效的检查顺序是:
- 运行
go mod verify,看是否报 missing hash 或 mismatch
- 对比
go.sum 行数和 vendor/modules.txt 行数,二者应基本一致(modules.txt 不含 // indirect 标记,但所有条目必须在 go.sum 中存在)
- 确认
go env GOMOD 指向项目根目录下的 go.mod,而不是某层父目录的——路径错会导致模块查找失败
最稳妥的做法是:在联网机上做完
go mod tidy →
go mod download →
go mod vendor →
go mod verify 全部通过,再打包整个项目目录(含
vendor/、
go.mod、
go.sum)过去。
真正麻烦的从来不是下载动作本身,而是模块元数据与底层系统能力的耦合。一次成功的离线构建,本质是把“联网时能自动补全的东西”,全部变成可验证、可搬运、可落地的确定性文件。