根本区别在于:net.LookupIP调用系统resolver,自动处理但不可控;net.Resolver是可控入口,支持自定义DNS服务器、context超时、查MX/TXT等非A记录及全量Pod IP,但必须同时设PreferGo:true和Dial函数才生效。

net.LookupIP 和 net.Resolver 的根本区别在哪
用 net.LookupIP 就是调系统 resolver(/etc/resolv.conf 或 Windows API),它自动处理重试、双栈、基础超时,但你完全没法干预。它只接受纯域名字符串,传 "example.com:443" 会报 *net.DNSError,Err 字段是 "no such host",不是格式错误。
net.Resolver 才是可控入口:能指定 DNS 服务器(比如 "1.1.1.1:53")、加 context 超时、查 MX/TXT/CNAME/PTR、拿全量 Pod IP。但它不是全局替换——不改 net.DefaultResolver,也不影响 http.DefaultClient,必须显式构造、显式调用。
-
PreferGo: true必须设,否则 fallback 到 cgo 的getaddrinfo,自定义Dial就失效 -
Dial是函数,不是字符串;返回net.Conn,不能只写地址 - 查非 A 记录(如
LookupMX、LookupTXT)只能走net.Resolver实例,net.LookupIP根本没这些方法
怎么正确配置 net.Resolver 的 Dial 和超时
Dial 函数里必须用 net.Dialer{Timeout: ...}.DialContext,否则连接层超时不生效。UDP 查公网 DNS(如 Cloudflare)用 "udp" + "1.1.1.1:53";TCP 查内网 CoreDNS 可能需要 "tcp",但注意有些服务默认拒收 TCP 查询。
- 别漏
KeepAlive:长连接场景下影响复用效果 -
net.Resolver本身没有超时字段,上下文超时靠context.WithTimeout包裹LookupIP调用,不是 Resolver 初始化时设的 - 错误要细判:
err.(*net.DNSError).IsNotFound()区分“域名不存在”,.IsTemporary()判断是否临时失败(如 UDP 丢包、防火墙拦截)
如何让 HTTP 请求也走自定义 DNS 解析
http.Client 不认 net.Resolver,也不能直接改 http.DefaultClient 或 net.DefaultResolver。必须通过 http.Transport.DialContext 注入逻辑:在 DialContext 里调你自己的 resolver.LookupHost,再拼 net.Dialer.DialContext 连接。
立即学习“go语言免费学习笔记(深入)”;
- 别用旧版
Dial(无 context 参数),否则 TLS 握手阶段仍走系统 DNS -
LookupHost返回的是字符串切片,记得选 IPv4/IPv6;若后端需 SNI 校验,TLSConfig.ServerName得填原始域名,不能填解析出的 IP - HTTP 连接池默认不缓存 DNS 结果(TTL=0),如需缓存,得自己在
DialContext里加 LRU 或 TTL 控制
反向解析(IP → 域名)该用哪个函数
别用 net.LookupHost 传 IP 字符串——它会当字面量主机名处理,返回原样 IP,不是 PTR 查询。必须用 net.LookupAddr,它专为反向解析设计,查的是 in-addr.arpa 或 ip6.arpa 下的 PTR 记录。
-
LookupAddr参数必须是合法 IP 字符串(如"1.1.1.1"或"2001:db8::1"),不能带端口、不能是域名 - 结果为空不一定是错,可能是管理员没配 PTR;错误类型仍是
*net.DNSError,可用.IsNotFound()判断 - 标准
net.LookupAddr不支持 context,如需超时,得自己包装net.Resolver实例并调resolver.LookupAddr
net.Resolver 行为都依赖 PreferGo: true + Dial 函数同时存在,缺一不可;而 HTTP 场景下,DialContext 的实现必须完整覆盖 DNS 解析 + 连接建立两步,漏掉任意一环都会回退到系统行为。


















