离线Go项目编译成功需三件事:联网机拉全依赖、关远程校验(GOPROXY=direct、GOSUMDB=off)、显式指定-go build -mod=vendor;replace本地路径需手动处理,vendor/modules.txt须与go.sum严格一致。

离线环境里 Go 项目能编译成功,不靠“禁用校验”或“硬改代码”,而靠三件事:提前在联网机拉全依赖、关掉远程校验链路、显式告诉 go build 去哪找代码。
go mod download 为什么在离线机上直接报 no such host
因为默认 GO111MODULE=on 时,go build 仍会尝试连接 proxy.golang.org 和 sum.golang.org,哪怕你本地有缓存。这不是网络不通的问题,是 Go 工具链主动发起的 DNS 查询。
- 必须在离线机执行:
go env -w GOPROXY=direct(不是空值,也不是off) - 必须执行:
go env -w GOSUMDB=off(设为""仍可能 fallback 到默认值) - 如果项目用了
replace指向私有 Git 地址(如git.internal.com/lib),还得加-mod=readonly参数防止自动修正,否则go build会尝试解析域名
vendor 目录为什么存在却 still fails to build
vendor/ 只是源码快照,它本身不会生效——Go 1.14+ 默认忽略 vendor,除非你显式传参。
- 编译必须加:
go build -mod=vendor,否则工具链仍走$GOPATH/pkg/mod查模块 -
go mod vendor不处理replace到本地路径的模块(如replace example.com/a => ../a),得手动复制或先用go mod edit -replace改成远端地址再 vendor -
vendor/modules.txt必须覆盖所有go.sum条目,否则go build -mod=vendor会校验失败,报checksum mismatch
离线构建前如何验证依赖已真正齐全
别信 go mod tidy 成功就万事大吉。真正离线 = 全程无 DNS 解析、无 TCP 连接尝试。
立即学习“go语言免费学习笔记(深入)”;
- 在联网机运行:
go list -m all,输出所有模块;再比对vendor/modules.txt是否逐行覆盖 - 运行:
go mod download -x,确认每个模块都落盘到$GOPATH/pkg/mod/cache/download/,路径要真实存在 - 检查是否有 cgo 依赖:
go list -f '{{.CgoFiles}}' ./...,若有,离线机必须装对应头文件(如libc6-dev)和静态库(如libpthread.a),否则报cannot find -lc
交叉编译时 CGO_ENABLED 和系统库的坑
国产 OS(麒麟、统信)或嵌入式目标常卡在这步:代码能编译,但运行时报 DNS 失败或 user: lookup uid 错误。
- 设
CGO_ENABLED=0会退回到纯 Go 实现,但net包无法读/etc/resolv.conf,DNS 解析失效 - 设
CGO_ENABLED=1(默认)则必须确保离线机有完整 C 工具链(gcc、pkg-config)和目标架构的系统库 - 关键包如
github.com/mattn/go-sqlite3建议提前在目标环境静态编译好,再用replace指向本地 .a 文件
最易被忽略的是:vendor 目录下不能有 go.mod,项目根目录的 go.mod 必须保持有效——它不是备份,而是唯一权威声明;IDE(如 VS Code)默认不识别 -mod=vendor,需在设置里显式传 GOFLAGS。


















