go test时模块下载卡在proxy.golang.org,根本原因是ci环境未配置goproxy=https://goproxy.cn,direct且未注入gonoproxy处理私有模块,需通过环境变量而非go env -w设置,并配合-go test -mod=readonly和godebug=netdns=cgo规避dns卡顿。

go test 时模块下载卡在 proxy.golang.org
自动化测试流程(如 CI/Runner)中执行 go test 前若触发 go mod download,而环境未预装依赖,就会现场拉取模块——此时若未配置代理或代理被拦截,会直接卡在 Get "https://proxy.golang.org/..." 上,报 context deadline exceeded 或无响应。
- CI 环境通常不继承开发者本地
go env配置,GOPROXY很可能仍是默认值https://proxy.golang.org,direct - 某些企业 CI 节点禁用外网出向,或 DNS 污染导致
proxy.golang.org解析失败,但错误日志只显示“timeout”,不提示 DNS 问题 - 即使设置了
GOPROXY=https://goproxy.cn,漏掉,direct会导致私有 GitLab/自建仓库模块无法拉取,测试因 missing module 失败
验证方式:在 CI 脚本中加一行 go env GOPROXY,输出必须为 https://goproxy.cn,direct;再手动运行 go mod download -v 观察最后卡在哪条 curl 请求。
CI 中设置 GOPROXY 的可靠写法
不要依赖 go env -w(它写入的是用户级配置,在无 home 目录的容器里可能失效),改用环境变量注入:
- GitHub Actions:
env: GOPROXY: https://goproxy.cn,direct - GitLab CI:
variables: GOPROXY: "https://goproxy.cn,direct" - Jenkins Pipeline:在
sh步骤前加export GOPROXY="https://goproxy.cn,direct"
额外加固:如果项目含内网模块(如 git.internal.company.com),必须配 GONOPROXY,否则会被镜像代理转发后 404:
export GONOPROXY="git.internal.company.com,192.168.0.0/16"
注意:多个域名用英文逗号分隔,**不能有空格**,且 GONOPROXY 必须和 GOPROXY 同时生效才起作用。
go test -mod=readonly 防止意外触发下载
有些测试会间接调用 go list 或依赖未声明的隐式模块,导致 go test 自动尝试下载——这在离线 CI 或严格网络策略下必然失败。
- 强制禁止任何模块变更:
go test -mod=readonly,遇到缺失模块直接报错,不尝试下载 - 更彻底的做法是提前在 CI 初始化阶段运行
go mod download并缓存$GOMODCACHE目录,后续测试复用本地包 - 若使用
go run启动测试辅助服务(如 mock server),需单独为其加-mod=readonly,否则它仍可能触发下载
这个参数不解决代理问题,但能让你快速区分:是网络超时,还是模块声明本身有遗漏。
超时不是网络问题,而是 DNS 卡住
CI 日志里看到 dial tcp [2606:4700::6810:15f]:443: i/o timeout 或长时间无输出,大概率不是代理不可达,而是 Go 默认的纯 Go DNS 解析器在特定网络环境下死锁。
- 临时验证:在 CI 脚本中加
go env -w GODEBUG=netdns=cgo,强制走系统getaddrinfo - 根本解法:在 CI 镜像中预装
libc-dev(如 Debian 系加apt-get install -y libc6-dev),确保 cgo 可用 - 若无法改镜像,可设
GODEBUG=netdns=off关闭 DNS 缓存(副作用是每次解析都走系统调用,略慢但稳定)
这点容易被忽略——你反复换代理地址、调超时时间都没用,其实只是 DNS 层没响应,Ctrl+C 都等不到返回。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











