使用Golang获取本地网络接口信息_列出所有IP与MAC

2次阅读

net.Interfaces()仅返回网卡基础信息,需调用iface.addrs()获取ip、iface.hardwareaddr获取mac;注意windows权限限制、链路本地ipv6过滤及ip类型断言,推荐用to4()和isloopback()判断有效ipv4。

使用Golang获取本地网络接口信息_列出所有IP与MAC

net.Interfaces() 获取所有网卡列表

go 标准库的 net.Interfaces() 是入口,但它只返回基础信息(名字、索引、标志),不带 IP 或 MAC。直接遍历返回的 []net.Interface 会发现 Addr 字段为空——这是新手最常卡住的地方。

  • 必须对每个 net.Interface 调用 iface.Addrs() 才能拿到 IP 地址(*net.IPNet 类型)
  • MAC 地址要通过 iface.HardwareAddr 获取,但注意:环回接口(如 lo)的 HardwareAddr.String() 可能返回空字符串00:00:00:00:00:00,不是 bug,是系统行为
  • 某些虚拟网卡(如 dockerbr-*、WSL2 的 vEthernet)可能有多个 IPv4/IPv6 地址,需自行过滤

区分 IPv4 和 IPv6 地址的正确方式

iface.Addrs() 返回的是 []net.Addr,实际类型可能是 *net.IPNet*net.IPAddr。不能靠字符串前缀(比如 “192.”)判断,得用 ip.To4() != nil

  • addr.(*net.IPNet).IP 是网络地址(含主机位),要取可用 IP 得用 addr.(*net.IPNet).IP.To4().IP.To16() 再检查非 nil
  • IPv6 链路本地地址(以 fe80:: 开头)通常不能用于外部通信,是否保留取决于你的场景;若只要“能用的 IP”,建议跳过 ip.IsLinkLocalUnicast()
  • 别漏掉 net.ParseIP("127.0.0.1") 这类 *net.IPAddr 类型地址——它们不会出现在 iface.Addrs() 中,但 net.Interface.Addrs() 实际也会返回部分 *net.IPAddr,需类型断言处理

绕过权限问题:Windows 上获取 MAC 的坑

在 Windows 上,非管理员进程调用 iface.HardwareAddr 对某些适配器(尤其是无线网卡、Hyper-V 虚拟网卡)可能返回空。这不是 Go 的限制,而是 Windows 网络的访问控制策略。

  • 不需要管理员权限也能拿到大部分有线网卡的 MAC,但无线网卡大概率失败
  • 如果必须拿到所有 MAC,可改用 exec.Command("getmac", "/fo", "csv", "/nh") 解析命令输出(注意路径和权限仍受限)
  • 更稳妥的做法是:当 iface.HardwareAddr.String() 为空时,记录为 "unknown" 并继续,而不是 panic 或重试

完整示例:只取 UP 状态、有 IPv4 且非回环的网卡

以下逻辑能覆盖大多数服务部署场景(比如自动绑定监听地址):

立即学习go语言免费学习笔记(深入)”;

interfaces, _ := net.Interfaces() for _, iface := range interfaces {     if iface.Flags&net.FlagUp == 0 || iface.Flags&net.FlagLoopback != 0 {         continue     }     addrs, _ := iface.Addrs()     for _, addr := range addrs {         if ipnet, ok := addr.(*net.IPNet); ok && ipnet.IP.To4() != nil {             ip := ipnet.IP.To4()             if !ip.Equal(net.IPv4zero) && !ip.IsLoopback() {                 fmt.Printf("iface: %s, ip: %s, mac: %sn",                     iface.Name,                     ip.String(),                     iface.HardwareAddr.String())             }         }     } }

注意 iface.HardwareAddr.String()linux/macOS 上稳定,但在 Windows 上可能为空;IP 判断用了 To4()IsLoopback() 两层过滤,比单纯字符串匹配可靠得多。

真正麻烦的不是代码长度,而是不同系统对“一个网卡该不该暴露 MAC”“链路本地地址算不算有效 IP”的隐式定义不一致——写死逻辑不如留好 fallback 路径。

text=ZqhQzanResources