如何使用Go语言net包读取Linux下指定虚拟网卡的IP地址
如何单独读取Linux中eth0:2的IP地址?
问题场景
通过ifconfig -a | grep -A2 eth0可以看到网卡eth0及其虚拟子接口的信息:
ifconfig -a | grep -A2 eth0 eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 100.180.89.148 netmask 255.255.255.224 broadcast 100.180.89.140 inet6 fe80::ac16:2dff:fead:a321 prefixlen 64 scopeid 0x20<link> -- eth0:1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 100.180.89.150 netmask 255.255.255.255 broadcast 100.180.89.150 ether cc:16:2d:ad:a3:20 txqueuelen 1000 (Ethernet) -- eth0:2: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 100.180.89.151 netmask 255.255.255.255 broadcast 100.180.89.151 ether ac:16:2d:ad:a3:20 txqueuelen 1000 (Ethernet) -- eth0:3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 100.180.89.152 netmask 255.255.255.255 broadcast 100.180.89.152 ether ac:16:2d:ad:a3:20 txqueuelen 1000 (Ethernet)
原Go代码遍历所有接口并输出eth0的所有地址,但输出包含了主接口和所有虚拟子接口的IP:
// nwkIfName = eth0 func networkInterfaces(nwkIfName string) ([]Interfaces, error) { ifaces, err := net.Interfaces() if err != nil { return nil, fmt.Errorf("failed to get network interfaces: %w", err) } for _, nwIf := range ifaces { fmt.Println(nwIf.Name) if nwIf.Name == nwkIfName { fmt.Println(nwIf.Addrs()) } } return nil, nil }
输出:
[100.180.89.148/27 100.180.89.150/32 100.180.89.151/32 100.180.89.152/32 fe80::ae16:2dff:fead:a320/64] <nil>
现在需要单独读取eth0:2的IP地址。
解决方法
在Linux系统中,eth0:2这类虚拟子接口会被Go标准库的net.Interfaces()识别为独立的网络接口,接口名称就是完整的eth0:2。直接通过匹配接口名称即可获取对应IP。
代码示例:获取指定虚拟子接口的IP
package main import ( "fmt" "net" ) // getVirtualInterfaceIP 获取指定虚拟网卡的IP地址 func getVirtualInterfaceIP(ifName string) ([]net.Addr, error) { ifaces, err := net.Interfaces() if err != nil { return nil, fmt.Errorf("获取网络接口失败: %w", err) } for _, iface := range ifaces { // 匹配目标虚拟子接口名称 if iface.Name == ifName { addrs, err := iface.Addrs() if err != nil { return nil, fmt.Errorf("获取接口%s地址失败: %w", ifName, err) } return addrs, nil } } return nil, fmt.Errorf("未找到接口%s", ifName) } func main() { // 传入目标虚拟子接口名称eth0:2 addrs, err := getVirtualInterfaceIP("eth0:2") if err != nil { fmt.Println(err) return } // 打印所有IP地址(含IPv4/IPv6) for _, addr := range addrs { fmt.Println(addr.String()) } }
扩展:获取主接口下所有虚拟子接口的IP
如果需要批量获取eth0下所有虚拟子接口(如eth0:1、eth0:2等)的IP,可以通过前缀匹配实现:
package main import ( "fmt" "net" "strings" ) // getSubInterfaceIPs 获取主接口下所有虚拟子接口的IP func getSubInterfaceIPs(mainIfName string) (map[string][]net.Addr, error) { ifaces, err := net.Interfaces() if err != nil { return nil, fmt.Errorf("获取网络接口失败: %w", err) } subIfAddrs := make(map[string][]net.Addr) // 构造虚拟子接口名称前缀,如eth0: prefix := mainIfName + ":" for _, iface := range ifaces { if strings.HasPrefix(iface.Name, prefix) { addrs, err := iface.Addrs() if err != nil { return nil, fmt.Errorf("获取接口%s地址失败: %w", iface.Name, err) } subIfAddrs[iface.Name] = addrs } } if len(subIfAddrs) == 0 { return nil, fmt.Errorf("未找到%s的虚拟子接口", mainIfName) } return subIfAddrs, nil } func main() { subIfs, err := getSubInterfaceIPs("eth0") if err != nil { fmt.Println(err) return } // 遍历打印所有虚拟子接口及其IP for ifName, addrs := range subIfs { fmt.Printf("接口%s的IP地址:\n", ifName) for _, addr := range addrs { fmt.Printf(" %s\n", addr.String()) } } }
内容的提问来源于stack exchange,提问作者James Sapam
相关产品推荐
相关产品推荐

