net.LookupHost 默认只返回 IPv4 地址(A 记录),不返回 IPv6(AAAA 记录),因其设计为粗粒度主机名到IP字符串映射,且内部依赖系统解析器;需IPv6应改用 net.LookupIP。

net.LookupHost 为什么查不到 IPv6 地址?
net.LookupHost 默认只返回 A 记录(IPv4),即使域名同时配置了 AAAA 记录,它也不会返回 IPv6 地址。这不是 bug,而是设计如此——它只做“主机名到 IP 列表”的粗粒度映射,不区分协议族。
常见错误现象:net.LookupHost("google.com") 返回 ["142.250.191.46"],但用 dig AAAA google.com 能看到 IPv6 地址,用户误以为解析失败或库有问题。
- 若需 IPv6,改用
net.LookupIP,它返回所有可用记录(A + AAAA) -
net.LookupHost内部调用的是系统gethostbyname(POSIX)或GetAddrInfoW(Windows),行为受系统 resolver 配置影响,不是 Go 自行 DNS 查询 - 在容器或精简镜像中(如
alpine:latest),/etc/resolv.conf缺失或 DNS 配置异常会导致LookupHost直接返回"no such host"
net.LookupIP 和 net.LookupHost 的关键区别在哪?
net.LookupIP 返回 []net.IP,含 IPv4 和 IPv6;net.LookupHost 返回 []string,仅 IPv4 字符串(且顺序不保证)。两者都走系统 resolver,但返回结构和语义不同。
使用场景:需要连接双栈服务时,net.LookupIP 更合适;仅做快速连通性检查(比如 ping 工具)可选 LookupHost,更轻量。
立即学习“go语言免费学习笔记(深入)”;
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
-
net.LookupIP对"localhost"可能返回127.0.0.1和::1,而LookupHost通常只返回"127.0.0.1" -
net.LookupIP的结果可直接传给net.Dial(如net.Dial("tcp", "google.com:443")内部就调用了它) - 注意:返回的
net.IP是扁平字节数组,IPv6 地址长度为 16 字节,别用len(ip)判断类型,应调用ip.To4()或ip.IsGlobalUnicast()
超时控制和错误处理怎么写才靠谱?
Go 标准库的 net.Lookup* 系列函数**不接受 context 或 timeout 参数**,它们是同步阻塞调用,超时由底层系统 resolver 控制(如 glibc 的 RES_TIMEOUT)。这意味着你无法在应用层精确中断一个卡住的 DNS 查询。
常见错误现象:DNS 服务器无响应时,LookupHost 卡住几十秒,拖垮整个 goroutine。
- 必须用
context.WithTimeout包裹调用,靠 goroutine + channel 实现超时:ch := make(chan []string, 1) errCh := make(chan error, 1) go func() { ips, err := net.LookupHost(host) if err != nil { errCh <- err } else { ch <- ips } }() select { case ips := <-ch: return ips, nil case err := <-errCh: return nil, err case <-ctx.Done(): return nil, ctx.Err() // 如 context.DeadlineExceeded } - 不要依赖
net.DefaultResolver(Go 1.11+ 引入),它默认仍走系统 resolver;自定义net.Resolver并设置PreferGo: true才启用 Go 原生解析器,支持WithContext - 错误值判断要具体:
url.Error中的Err可能是*net.DNSError,可通过err.(*net.DNSError).IsNotFound区分“域名不存在”和“网络不可达”
在 Docker 或 Kubernetes 里解析失败怎么办?
DNS 解析失败在容器环境极其常见,根本原因往往不是 Go 代码问题,而是容器网络配置或宿主机 DNS 转发链路断裂。
典型错误信息:lookup example.com: no such host,但宿主机上 nslookup example.com 正常。
- 检查容器内
/etc/resolv.conf:Docker 默认继承宿主机的nameserver,但若宿主机用systemd-resolved(如 Ubuntu 20.04+),其127.0.0.53在容器内不可达,需启动容器时加--dns 8.8.8.8 - Kubernetes Pod 中,若
dnsPolicy: Default,会用节点 DNS;若ClusterFirst,则走 kube-dns/CoreDNS,此时需确认 CoreDNS 是否健康、是否配置了 upstream - Go 程序编译时用
CGO_ENABLED=0会强制使用 Go 原生 resolver(不依赖 libc),但会丢失/etc/nsswitch.conf和 SRV 记录支持,调试时建议先关掉该选项验证
Go 的 DNS 解析表面简单,实际深度耦合操作系统行为;真正难的不是写对一行 net.LookupHost,而是当它返回空或卡住时,能快速定位到底是代码、容器网络、还是上游 DNS 的问题。

















