离线部署前必须在有网机器执行go mod download,因go模块机制默认强依赖网络,离线机上该命令会卡死或报proxy.golang.org错误;唯一可行路径是在版本一致的联网机上运行go mod tidy和go mod download,完整落盘至$gopath/pkg/mod/cache/download/,再打包拷贝到离线机对应路径,并设goproxy=direct和gosumdb=off。

离线部署前必须在有网机器上执行 go mod download
离线环境里 go mod download 会卡死或报 proxy.golang.org: no such host,这不是配置问题,是 Go 模块机制默认强依赖网络。你不能指望在离线机上“边编译边拉包”。唯一可行路径,是在与目标环境 Go 版本完全一致(如 go1.21.6)的联网机器上,把所有依赖完整落盘到本地缓存目录。
关键动作只有两步:go mod tidy 确保 go.mod 和 go.sum 齐全且无未提交修改;再运行 go mod download -x,观察输出路径,确认每个模块都写入了 $GOPATH/pkg/mod/cache/download/ 子目录(注意不是 pkg/mod/,而是 cache/download/)。
- 如果项目含
replace到私有 Git 地址(如github.com/internal/lib),必须先git clone对应仓库,再用go mod edit -replace=github.com/internal/lib=./internal/lib改为相对路径,否则go mod download会跳过它 - 执行
go list -m all | wc -l记下模块总数,打包后在离线机验证时可比对是否一致 - 不要用
go mod vendor替代——它不处理// indirect依赖,也不包含replace的本地模块,且对 ARM64 麒麟等异构系统不友好
$GOPATH/pkg/mod/cache/download/ 目录结构不能扁平化
打包时必须保留原始层级:比如 github.com/gorilla/mux/@v/v1.8.0.zip 这种带 @v/ 和版本号的路径,是 Go 模块缓存的硬编码格式。如果解压后变成平铺的 gorilla-mux-v1.8.0/,Go 就找不到模块。
常见错误是用 tar -cf cache.tar pkg/mod/cache/download 但没进到 download 目录下执行,导致顶层多了一层 download/,离线机解压后路径变成 download/download/...,Go 查找失败。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
- 正确打包命令:
cd $GOPATH/pkg/mod/cache && tar -cf download.tar download/ - 离线机解压位置必须严格对应:
mkdir -p $GOPATH/pkg/mod/cache && tar -xf download.tar -C $GOPATH/pkg/mod/cache - 验证方式:
go list -m all不报错、输出模块列表完整,且go build能通过
离线机上必须设 GOPROXY=direct,不能留空或沿用默认值
即使你已拷贝全部缓存,若 GOPROXY 还是 https://proxy.golang.org 或未设置,Go 仍会尝试连接代理域名,超时后才 fallback 到本地缓存,整个构建过程可能卡住 2 分钟以上,日志只显示 “Fetching …”,没有明确错误提示。
设 GOPROXY=direct 是强制 Go 完全跳过网络代理,只查本地缓存。同时必须配 GOSUMDB=off(或指向内网 sumdb),否则 go build 仍会尝试访问 sum.golang.org 校验哈希。
- 临时生效:
go env -w GOPROXY=direct GOSUMDB=off - CI/CD 或 Docker 构建中,应在
ENV指令里显式声明:ENV GOPROXY=direct GOSUMDB=off - 验证:
go env GOPROXY GOSUMDB输出应为direct和off,不是空值或原始官网地址
私有模块和 replace 路径在离线机需二次修正
预拉取时用了 go mod edit -replace 指向本地相对路径,但打包后拷贝到离线机,该路径可能失效——比如开发机上 ./internal/lib 在离线机对应位置是 ../lib,或者项目根目录层级不同。
此时不能靠重跑 go mod download(它不处理 replace),而要手动在离线机上重新运行 go mod edit,确保路径真实存在且可读。
- 检查路径有效性:
ls -d ./internal/lib或ls -d ../lib - 修正命令:
go mod edit -replace=github.com/internal/lib=../lib(注意等号两边不能有空格) - 如果私有模块没打 tag,
go list -m all可能显示github.com/internal/lib v0.0.0-00010101000000-000000000000,这是正常现象,只要路径能访问即可
GOPROXY=direct 和 GOSUMDB=off 的组合必须同时生效,缺一不可;还有就是 cache/download/ 目录结构一旦扁平或路径错位,Go 就完全无法识别已下载的模块,连报错都未必出现,只会静默失败。golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










