Go mod download卡在resolving…是DNS问题的典型信号,根源在于宿主机DNS配置错误导致Go进程挂起在net.Resolver调用上,需检查/etc/resolv.conf是否被systemd-resolved或Docker覆盖,并通过dig验证proxy.golang.org解析结果。

Go mod download 卡在 resolving… 是 DNS 问题的典型信号
当你执行 go mod download 或 go build 时长时间停在 resolving …、verifying …,且 curl https://proxy.golang.org 能通但模块拉不下来,大概率是 DNS 解析失败——Go 的模块代理协议(如 https://proxy.golang.org)依赖 DNS 正确解析域名,而宿主机 DNS 配置错误会导致 Go 进程卡在 net.Resolver 的底层调用上,不报错、不超时、只挂起。
检查 /etc/resolv.conf 是否被 systemd-resolved 或 Docker 覆盖
Linux 宿主机常见陷阱:systemd-resolved 动态管理 /etc/resolv.conf,实际指向 /run/systemd/resolve/stub-resolv.conf(仅监听 127.0.0.53),而该地址在容器或某些 Go 网络栈中无法访问;Docker Desktop 或 WSL2 启动后也常覆盖该文件为 nameserver 127.0.0.11(Docker 内建 DNS),但 Go 默认不走该服务。
- 运行
cat /etc/resolv.conf,若看到nameserver 127.0.0.53或nameserver 127.0.0.11,基本确认问题来源 - 临时验证:执行
sudo rm /etc/resolv.conf && sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf(恢复真实上游 DNS) - 更稳妥做法是禁用 stub resolver:
sudo systemctl disable --now systemd-resolved,再手动写入可靠 DNS(如nameserver 8.8.8.8)
Go 不读取 /etc/resolv.conf?其实是读的,但受 CGO 和 netgo 影响
Go 默认使用纯 Go 实现的 DNS 解析器(netgo),它会读取 /etc/resolv.conf;但若启用了 CGO(即 CGO_ENABLED=1),则 fallback 到系统 libc 的 getaddrinfo,此时行为取决于 glibc 版本和 NSS 配置,可能绕过 /etc/resolv.conf 直接查 systemd-resolved socket。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 强制 Go 用纯 Go 解析器:
CGO_ENABLED=0 go mod download,若此时恢复正常,说明是 CGO + 系统 DNS 链路异常 - 检查当前生效解析器:
go env GODEBUG中是否含netdns=,默认为空即自动选择;可显式指定GODEBUG=netdns=go - 注意:交叉编译或某些 Alpine 镜像中
CGO_ENABLED=0是默认值,反而更稳定
排查 proxy.golang.org 域名是否被本地 DNS 污染或拦截
即使 /etc/resolv.conf 正确,某些企业网络、DNS 服务商(如国内部分宽带 DNS)会劫持或缓存错误的 proxy.golang.org 解析结果(例如返回 0.0.0.0 或私有 IP),导致 HTTPS 连接失败但 Go 不立即报错,而是反复重试并最终挂起。
立即学习“go语言免费学习笔记(深入)”;
- 手动验证解析:
dig +short proxy.golang.org @8.8.8.8,应返回多个全球 CDN IP(如142.250.185.14类似);若返回空、超时或内网地址,就是污染 - 绕过本地 DNS:在
go env -w GOPROXY=https://proxy.golang.org,direct前加GODEBUG=netdns=cgo+2查看详细解析日志 - 终极方案:改用可信 DNS 并固定:
echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf,然后重启 Go 进程(环境变量变更需新 shell)
真正麻烦的不是配置本身,而是 DNS 异常往往不抛错、不超时、不打印日志——它只是安静地让 Go 在 lookupIPAddr 里等一个永远不会回来的响应。动手前先 dig 和 strace -e trace=connect,sendto,recvfrom go mod download 2>&1 | head -20 看一眼系统调用,比猜快得多。

















