在 Go 语言中,获取域名的 IP 地址和 DNS 信息有多种方法,下面介绍几种常用的实现方式:
![图片[1]_Golang 获取域名 DNS 信息的几种方法_知途无界](https://zhituwujie.com/wp-content/uploads/2025/07/d2b5ca33bd20250703101945.png)
1. 使用 net.Lookup 系列函数
Go 标准库中的 net 包提供了几个方便的 DNS 查询函数:
package main
import (
"fmt"
"net"
)
func main() {
// 获取域名的所有 A 记录 (IPv4 地址)
ips, err := net.LookupIP("example.com")
if err != nil {
fmt.Println("LookupIP error:", err)
return
}
fmt.Println("IP addresses:")
for _, ip := range ips {
fmt.Println(ip)
}
// 获取域名的 CNAME 记录
cname, err := net.LookupCNAME("www.example.com")
if err != nil {
fmt.Println("LookupCNAME error:", err)
return
}
fmt.Println("CNAME:", cname)
// 获取域名的 MX 记录
mxs, err := net.LookupMX("example.com")
if err != nil {
fmt.Println("LookupMX error:", err)
return
}
fmt.Println("MX records:")
for _, mx := range mxs {
fmt.Printf("Host: %s, Pref: %d\n", mx.Host, mx.Pref)
}
// 获取域名的 TXT 记录
txts, err := net.LookupTXT("example.com")
if err != nil {
fmt.Println("LookupTXT error:", err)
return
}
fmt.Println("TXT records:")
for _, txt := range txts {
fmt.Println(txt)
}
// 获取域名的 NS 记录
nss, err := net.LookupNS("example.com")
if err != nil {
fmt.Println("LookupNS error:", err)
return
}
fmt.Println("NS records:")
for _, ns := range nss {
fmt.Println(ns.Host)
}
}
2. 使用 net.Resolver 进行更灵活的 DNS 查询
如果需要更细粒度的控制,可以使用 net.Resolver:
package main
import (
"context"
"fmt"
"net"
"time"
)
func main() {
r := &net.Resolver{
PreferGo: true,
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
d := net.Dialer{
Timeout: time.Millisecond * time.Duration(10000),
}
return d.DialContext(ctx, "udp", "8.8.8.8:53")
},
}
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
// 查询 A 记录
ips, err := r.LookupIPAddr(ctx, "example.com")
if err != nil {
fmt.Println("LookupIPAddr error:", err)
return
}
fmt.Println("IP addresses:")
for _, ip := range ips {
fmt.Println(ip.IP)
}
// 查询 SRV 记录
_, srvs, err := r.LookupSRV(ctx, "service", "tcp", "example.com")
if err != nil {
fmt.Println("LookupSRV error:", err)
return
}
fmt.Println("SRV records:")
for _, srv := range srvs {
fmt.Printf("Target: %s, Port: %d, Priority: %d, Weight: %d\n",
srv.Target, srv.Port, srv.Priority, srv.Weight)
}
}
3. 使用第三方库 (如 github.com/miekg/dns)
对于更高级的 DNS 查询需求,可以使用专业的 DNS 库:
package main
import (
"fmt"
"github.com/miekg/dns"
)
func main() {
domain := "example.com"
server := "8.8.8.8:53" // Google Public DNS
c := new(dns.Client)
m := new(dns.Msg)
m.SetQuestion(dns.Fqdn(domain), dns.TypeA)
m.RecursionDesired = true
r, _, err := c.Exchange(m, server)
if err != nil {
fmt.Println("DNS query error:", err)
return
}
if r.Rcode != dns.RcodeSuccess {
fmt.Println("DNS query failed:", dns.RcodeToString[r.Rcode])
return
}
fmt.Println("DNS records:")
for _, ans := range r.Answer {
switch record := ans.(type) {
case *dns.A:
fmt.Printf("A record: %s\n", record.A)
case *dns.AAAA:
fmt.Printf("AAAA record: %s\n", record.AAAA)
case *dns.CNAME:
fmt.Printf("CNAME record: %s\n", record.Target)
case *dns.MX:
fmt.Printf("MX record: %s (pref %d)\n", record.Mx, record.Preference)
case *dns.TXT:
fmt.Printf("TXT record: %s\n", record.Txt)
case *dns.NS:
fmt.Printf("NS record: %s\n", record.Ns)
}
}
}
4. 获取本地 DNS 配置
如果需要查看系统的 DNS 配置:
package main
import (
"fmt"
"net"
)
func main() {
// 获取系统 DNS 配置
conf, err := net.ResolverConfigFile()
if err != nil {
fmt.Println("Error getting resolver config:", err)
return
}
fmt.Println("Resolver config file:", conf)
// 获取系统 DNS 服务器
servers, err := net.LookupNS(".")
if err != nil {
fmt.Println("Error getting system DNS servers:", err)
return
}
fmt.Println("System DNS servers:")
for _, s := range servers {
fmt.Println(s.Host)
}
}
注意事项
- DNS 缓存:Go 的 net 包会缓存 DNS 查询结果,可以使用
net.DefaultResolver.PreferGo = true绕过系统缓存 - 超时处理:生产环境中应该总是设置合理的超时
- 并发限制:大量 DNS 查询时需要考虑并发限制
- DNS 服务器选择:对于关键应用,建议指定可靠的 DNS 服务器而非依赖系统默认
以上方法可以根据实际需求选择使用,标准库方法适合大多数简单场景,而第三方库则提供了更专业的 DNS 查询能力。
© 版权声明
文中内容均来源于公开资料,受限于信息的时效性和复杂性,可能存在误差或遗漏。我们已尽力确保内容的准确性,但对于因信息变更或错误导致的任何后果,本站不承担任何责任。如需引用本文内容,请注明出处并尊重原作者的版权。
THE END

























暂无评论内容