离线构建失败需显式设置 GOPROXY=direct、GOSUMDB=off、GO111MODULE=on;依赖缓存须完整打包 $GOPATH/pkg/mod/cache/download/;vendor 构建必须加 -mod=vendor 参数;交叉编译应禁用 CGO 以避免 ELF 兼容问题。

离线构建失败,先看是不是 GOPROXY 和 GOSUMDB 没关对
离线环境下 go build 卡在 verifying github.com/xxx@v1.2.3 或直接报 proxy.golang.org: no such host,根本不是网络不通,而是 Go 仍在尝试连接远程服务。必须显式关闭代理和校验机制:
-
go env -w GOPROXY=direct—— 注意是direct,不是off或空值;设为off会 fallback 到默认值 -
go env -w GOSUMDB=off—— 必须是off,设为空字符串""仍可能触发默认校验 -
go env -w GO111MODULE=on—— 防止旧脚本意外关闭模块模式
验证是否生效:go env GOPROXY GOSUMDB 应输出 direct off。如果仍失败,说明环境变量没被子进程继承(比如 CI 脚本或 systemd 服务),需写入 /etc/profile.d/golang.sh 并重启 shell。
依赖缓存怎么打包才真正可用
只拷贝 $GOPATH/pkg/mod 目录不够,go mod download 实际落盘路径是 $GOPATH/pkg/mod/cache/download/,而校验数据(.info、.mod、.zip)全在这里。常见错误是打包了整个 mod/ 但漏掉 cache/download/ 子目录,导致 go build 找不到模块内容。
- 在联网机器上,用目标 Go 版本(如
go1.24.5)执行:go mod download -x,确认所有模块都写入$GOPATH/pkg/mod/cache/download/ - 打包命令必须保留层级:
tar -czf gomod-cache.tar.gz -C $GOPATH/pkg/mod/cache download/ - 离线机解压时,路径要严格一致:
tar -xzf gomod-cache.tar.gz -C $GOPATH/pkg/mod/cache/ - 别用
go clean -modcache—— 这会清空你刚拷过来的全部缓存
vendor 目录为什么还是连网失败
go mod vendor 生成的 vendor/ 看似“全量”,但离线构建时仍可能失败,因为 Go 默认仍会读取 $GOPATH/pkg/mod 中的校验和或间接依赖。关键是要强制它只认 vendor/:
立即学习“go语言免费学习笔记(深入)”;
- 构建命令必须加
-mod=vendor:例如go build -mod=vendor -o myapp - 确保
GO111MODULE=on(Go 1.16+ 默认开启),否则-mod=vendor不生效 - 检查
vendor/modules.txt是否覆盖go.sum中所有条目;若含私有模块且用了replace,vendor不会自动包含它们,得手动git clone并go mod edit -replace成本地路径 -
go build -v输出里必须看到vendor/被扫描,而不是$GOROOT/src或$GOPATH/pkg/mod
交叉编译产物在目标机报错 not a valid ELF executable 怎么办
这不是依赖问题,而是 CGO 和平台兼容性混在一起了。本地 go build -o app-linux-arm64 成功,但目标机运行失败,大概率是动态链接了宿主机 libc。
- 优先禁用 CGO:
CGO_ENABLED=0 go build -o app-linux-arm64。纯 Go 实现虽可能丢部分功能(如 DNS 解析),但二进制可移植性最高 - 若必须启用 CGO(如调用 C 库),则目标机需预装对应头文件和静态库(如
libc6-dev、libpthread.a),且 Go 编译时要指定CC工具链路径 - 确认目标架构真实值:
uname -m在目标机上跑,别信文档写的 “ARM64”——实际可能是aarch64或arm64,两者不等价 - 构建前清缓存:
go clean -cache -modcache,尤其从 macOS 编译 Linux 时,$HOME/Library/Caches/go-build可能残留 darwin 构建物
最易忽略的一点:离线部署不是“把代码拷过去就行”,而是整个构建链路(Go 版本、缓存结构、环境变量、CGO 状态)必须与目标环境完全对齐。任何一环版本或配置错位,都会在运行时才暴露,而非编译时报错。


















