离线构建前必须在联网机用目标go版本执行go mod download拉全依赖,确保$gocache/pkg/mod/cache/download/下每个模块都有.zip和.info文件,并同步打包replace的本地代码;离线机须设goproxy=direct、gosumdb=off、go111module=on,环境变量应写入/etc/profile.d/golang.sh以全局生效。

离线构建前必须拉全依赖缓存
只复制 go.mod 和 vendor/ 目录,不等于离线可用。Go 构建时仍会尝试从 $GOCACHE/pkg/mod/cache/download/ 读取模块 zip 和 info 文件——哪怕用了 go build -mod=vendor,它也会校验这些缓存是否存在,尤其对 // indirect 标记的间接依赖。
正确做法是在联网机器上执行:
-
GO111MODULE=on go mod download(确保所有go list -m all输出的模块都落盘) - 检查
$GOCACHE/pkg/mod/cache/download/下每个模块是否都有.zip和.info文件(例如golang.org/x/net@v0.28.0.zip) - 若项目含
replace,需同步把被替换的本地代码目录一并打包,不能只靠vendor/
离线机上必须关闭代理和校验
即使 go.mod 存在、vendor/ 完整,go build 仍可能卡在 verifying github.com/xxx: checksum mismatch 或 no such host ——这是 Go 默认启用 GOSUMDB 和尝试连接 proxy.golang.org 导致的。
必须在离线机上显式设置:
-
go env -w GOPROXY=direct(不是off或空值) -
go env -w GOSUMDB=off(设为off才真正禁用,设为空字符串仍 fallback) -
go env -w GO111MODULE=on(避免退化到 GOPATH 模式) - 验证:运行
go env GOPROXY GOSUMDB,输出应为direct off
vendor 目录不是“一键离线”保险箱
go mod vendor 不下载新模块,只复制已缓存的依赖;它也不处理测试依赖、//go:embed 引用的非 Go 文件、或 replace 后的真实源码路径。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
常见失效场景:
- 执行
go mod vendor前没跑过go mod download,vendor/实际是空壳 - 项目有
_test.go引入了额外包,但go test没触发过,那些包不会进vendor/ -
vendor/modules.txt被手动删或修改,go build -mod=vendor会直接拒绝使用 vendor -
replace指向本地路径(如replace example.com/a => ../a),vendor/里对应目录为空,构建时仍需该路径存在且可读
环境变量配置必须全局生效
写进 ~/.bashrc 很容易失效——CI 脚本、systemd 服务、VS Code 终端、Docker 构建都可能不加载它。
真正可靠的方式是:
- 解压 Go 到
/usr/local/go,确保/usr/local/go/bin/go可执行 - 创建
/etc/profile.d/golang.sh,内容为:
export GOROOT=/usr/local/go export PATH=$GOROOT/bin:$PATH export GOPATH=$HOME/go export PATH=$GOPATH/bin:$PATH
然后执行 source /etc/profile.d/golang.sh,新开终端运行 go env GOROOT 验证是否输出路径。若为空,说明 shell 启动时根本没加载该文件。
架构错配也常被忽略:ARM 机器上用了 amd64 的 tar 包,go version 成功但 go list -m all panic,必须核对 go1.24.5.linux-arm64.tar.gz 这类文件名里的 arm64。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










