离线环境无法执行 go mod download 或 go get,必须在同版本 go 的联网机器上预拉取完整依赖并拷贝 cache/download 目录,同时设置 goproxy=direct、gosumdb=off、go111module=on,并确保 go.mod 和 go.sum 齐全。

离线平台无法执行 go mod download 或 go get,这不是配置问题,而是 Go 模块机制本身的设计限制——它默认强依赖网络解析、TLS 握手和远程校验。唯一可行路径,是在有网且 Go 版本完全一致的机器上预拉取完整依赖树,再拷贝到离线机。
必须用目标环境同版本 Go 执行预下载
不同 Go 版本对 // indirect 依赖的处理、go.sum 哈希算法、模块路径解析规则都可能不兼容。比如在 go1.22.3 上拉取的缓存,在 go1.21.6 离线机上会报 verifying module: checksum mismatch。
- 先确认目标离线机的 Go 版本:
go version,例如输出go version go1.21.6 linux/arm64 - 在联网机器上安装**完全相同版本**的 Go(不能是 1.21.x,必须是 1.21.6)
- 运行
go mod download -x,观察输出中所有模块是否都落盘到$GOPATH/pkg/mod/cache/download/目录下 - 若项目含
replace到私有 Git 地址(如github.com/internal/log),需提前git clone对应仓库,并用go mod edit -replace=github.com/internal/log=./internal/log改为相对路径
打包时必须保留完整目录结构
go mod download 写入的是 $GOPATH/pkg/mod/cache/download/ 下带哈希后缀的子目录(如 github.com/gorilla/mux/@v/v1.8.0.zip),不是扁平化的源码包。直接复制 vendor/ 或只拷贝 src/ 会失效。
- 打包命令建议用:
tar -czf mod-cache.tar.gz -C $GOPATH/pkg/mod cache/download/ - 解压到离线机时,路径必须与原
$GOPATH一致(如离线机设GOPATH=/home/user/go,就解压到/home/user/go/pkg/mod/cache/download/) - 别漏掉
go.mod和go.sum文件——它们是模块验证的依据,缺一不可
离线机上必须关闭网络校验行为
即使缓存齐全,Go 默认仍会尝试连接 proxy.golang.org 和 sum.golang.org,导致卡在 DNS 解析或 TLS 握手阶段,报错类似 proxy.golang.org: no such host 或 timeout。
- 设环境变量:
GOPROXY=direct(禁用代理) +GOSUMDB=off(跳过校验) +GO111MODULE=on(强制启用模块) - 验证是否生效:
go list -m all应快速输出全部模块,无任何网络等待或错误 - 若用 Docker 构建,
Dockerfile中需显式写ENV GOPROXY=direct GOSUMDB=off,且go mod download必须放在COPY go.mod go.sum .之后、COPY . .之前
常见失败现象及定位方法
构建失败时,别只看第一行报错。真正的问题往往藏在模块验证或路径拼接环节。
-
missing required module:通常是go.sum缺失,或某模块哈希不匹配,运行go mod verify可暴露具体模块 -
unknown revision:说明该模块没被go mod download拉取,检查go list -m all输出是否包含它,再查$GOPATH/pkg/mod/cache/download/下对应路径是否存在 -
cannot find package "golang.org/x/net/http2":这是标准库扩展,不会随 Go SDK 自带,必须在联网机上单独go mod download golang.org/x/net并打包 - 构建时出现
go: downloading ...日志:说明GOPROXY没生效,或环境变量未被构建进程继承(如 CI 中未 export)
真正离线意味着从 go mod download 到 go build 全程无任何域名解析、TCP 连接尝试。最可靠的验证方式,是在离线机上用 strace -e trace=connect,openat go build 抓系统调用——如果出现任何 connect 尝试,说明还有地方没关干净。











