直接结论:不能只配goproxy指向公网镜像,内网机器根本连不上——必须部署本地可访问的代理服务(如athens)或彻底离线预缓存;因goproxy.cn是公网地址且内网禁出、sum.golang.org同样不可达,会导致go mod download卡死或checksum mismatch,私有模块还因未配goprivate被错误转发而404。

直接结论:不能只配 GOPROXY 指向公网镜像(如 https://goproxy.cn),内网机器根本连不上——必须部署本地可访问的代理服务,或彻底离线预缓存。
为什么 goproxy.cn 在内网一定失败
它本质是公网地址,企业防火墙通常禁止出向 HTTPS 请求;即便开了白名单,也违背“内网隔离”安全策略。更隐蔽的问题是:go mod download 会额外请求 sum.golang.google.cn 校验和,这个域名在内网同样不可达,直接卡死或报 verifying xxx: checksum mismatch。
常见错误现象:
- 执行
go mod tidy卡在Fetching,10 分钟后超时 - 看似成功下载,但构建时报
checksum mismatch,根源是校验服务没响应,go工具链 fallback 到空校验逻辑,导致哈希不一致 - 私有模块(如
git.company.com/internal/lib)被代理强行转发,返回 404 或认证错误
正确做法:用 Athens 搭建内网 Go 代理
Athens 是 Go 官方推荐的私有代理实现,能完整处理 .info、.mod、.zip 协议,支持私有模块透传与校验闭环,不是简单反向代理。
最小可行部署(Docker):
docker run -d \ --name athens \ --restart=always \ -p 3000:3000 \ -v /path/on/host/storage:/var/lib/athens \ -e ATHENS_DISK_STORAGE_ROOT=/var/lib/athens \ -e ATHENS_GO_BINARY=/usr/local/go/bin/go \ gomods/athens:v0.35.0
关键点:
- 容器监听内网可访问地址(如
http://athens.internal:3000),不要加 trailing slash(http://athens.internal:3000/会导致go工具链解析失败) - 挂载持久化目录,否则重启后缓存全丢
- 客户端配置必须同步设置
GOPRIVATE=git.company.com/*,否则私有模块仍走公网校验 -
GOSUMDB=sum.golang.google.cn要保留,Athens 会代理该请求;若完全断网,需自建 sumdb 或设为off(仅限测试)
完全断网场景:离线预缓存 + GOPROXY=direct
适用于无任何外网通道的生产环境(如军工、金融核心系统),依赖必须提前打包带入。
操作流程:
- 在有网机器上,确保项目
go.mod和go.sum已提交且稳定 - 运行
go mod download -json查看将拉取哪些模块,核对版本是否符合预期 - 执行
go mod download,所有模块写入$GOPATH/pkg/mod/cache - 打包整个
pkg/mod/cache目录(保留结构),拷贝到离线机相同路径 - 离线机执行
go env -w GOPROXY=direct(不是off,也不是留空)
容易踩的坑:
- 误用
go clean -modcache—— 这会清掉你唯一可用的缓存 -
go.sum文件含 Windows CRLF 换行符或末尾空格,导致校验失败;用dos2unix或编辑器转 LF - Docker 构建时未把
go.mod和go.sum提前COPY,导致go mod download阶段触发网络请求
GOPROXY 多地址逗号分隔的真实行为
很多人以为写成 GOPROXY=https://athens.internal:3000,https://goproxy.cn,direct 是容灾,实际是徒增延迟。
Go 的行为是严格顺序尝试:
- 先请求
https://athens.internal:3000,超时(默认 30 秒)后才试下一个 -
https://goproxy.cn在内网必然失败,白白浪费 30 秒 - 只有前一个返回明确的
404或410,才会触发direct回源
所以生产环境应只写:GOPROXY=http://athens.internal:3000,direct(HTTP 即可,除非你配了 TLS)
真正复杂的是私有模块域名管理:GOPRIVATE 必须精确匹配 Git 地址前缀,比如 gitlab.corp.example.com/internal/* 和 github.com/company/* 要分开列,漏掉任何一个都会导致校验失败或连接拒绝。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











