golang 获取本地IP地址
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了golang 获取本地IP地址相关的知识,希望对你有一定的参考价值。
如何从本地接口获取所有地址和掩码?
【中文标题】如何从本地接口获取所有地址和掩码?【英文标题】:How to get all addresses and masks from local interfaces in go? 【发布时间】:2014-06-25 03:08:09 【问题描述】:如何从 golang 的本地接口获取所有地址和掩码?
我需要与每个 IP 地址一起配置的实际网络掩码。
此代码在 Windows 7 中不显示网络掩码:
package main
import (
"fmt"
"log"
"net"
)
func localAddresses()
ifaces, err := net.Interfaces()
if err != nil
log.Print(fmt.Errorf("localAddresses: %v\n", err.Error()))
return
for _, i := range ifaces
addrs, err := i.Addrs()
if err != nil
log.Print(fmt.Errorf("localAddresses: %v\n", err.Error()))
continue
for _, a := range addrs
log.Printf("%v %v\n", i.Name, a)
func main()
localAddresses()
更新:此问题已在 Go 中修复:https://github.com/golang/go/issues/5395
【问题讨论】:
【参考方案1】:net.Interface
可能有多种类型的地址。 Addr
只是一个可能包含net.IPAddr
的接口。但是通过类型断言或类型切换,您可以访问实际的地址类型:
package main
import (
"fmt"
"net"
)
func localAddresses()
ifaces, err := net.Interfaces()
if err != nil
fmt.Print(fmt.Errorf("localAddresses: %+v\n", err.Error()))
return
for _, i := range ifaces
addrs, err := i.Addrs()
if err != nil
fmt.Print(fmt.Errorf("localAddresses: %+v\n", err.Error()))
continue
for _, a := range addrs
switch v := a.(type)
case *net.IPAddr:
fmt.Printf("%v : %s (%s)\n", i.Name, v, v.IP.DefaultMask())
func main()
localAddresses()
编辑
不幸的是,net
包没有返回地址的掩码。因此,您将不得不执行 net
包所做的低级系统调用。下面的代码是一个例子,但仍然需要解析ip和掩码:
package main
import (
"fmt"
"net"
"os"
"syscall"
"unsafe"
)
func getAdapterList() (*syscall.IpAdapterInfo, error)
b := make([]byte, 1000)
l := uint32(len(b))
a := (*syscall.IpAdapterInfo)(unsafe.Pointer(&b[0]))
// TODO(mikio): GetAdaptersInfo returns IP_ADAPTER_INFO that
// contains IPv4 address list only. We should use another API
// for fetching IPv6 stuff from the kernel.
err := syscall.GetAdaptersInfo(a, &l)
if err == syscall.ERROR_BUFFER_OVERFLOW
b = make([]byte, l)
a = (*syscall.IpAdapterInfo)(unsafe.Pointer(&b[0]))
err = syscall.GetAdaptersInfo(a, &l)
if err != nil
return nil, os.NewSyscallError("GetAdaptersInfo", err)
return a, nil
func localAddresses() error
ifaces, err := net.Interfaces()
if err != nil
return err
aList, err := getAdapterList()
if err != nil
return err
for _, ifi := range ifaces
for ai := aList; ai != nil; ai = ai.Next
index := ai.Index
if ifi.Index == int(index)
ipl := &ai.IpAddressList
for ; ipl != nil; ipl = ipl.Next
fmt.Printf("%s: %s (%s)\n", ifi.Name, ipl.IpAddress, ipl.IpMask)
return err
func main()
err := localAddresses()
if err != nil
panic(err)
从 interface_windows.go 中无耻地借用了一些代码。甚至 cmets 也完好无损
【讨论】:
我需要实际的掩码,而不是有类的默认值。我看到 net.IPNet 类型提供了 net.IPNet.Mask。有没有办法将地址读取为 net.IPNet? 查看net
包的文档/源代码,我看到他们只提供IP。因此,您需要做的是改用 syscall
包。我会更新我的答案。
不错!但是它只显示一个接口的地址/掩码。固定在这里:play.golang.org/p/kJ0P7HnvDE 请更新答案然后我接受它!谢谢。
@Everton 啊,是的。我看到了我的错误。我已经用你的错误修复更新了代码。欢迎:)
syscall.IpAdapterInfo 在 Go 1.5 上有一些问题,它将在 Go 1.6 中修复。参考github.com/golang/go/issues/12551【参考方案2】:
我正在修改@ANisus 答案并获取所有接口和掩码(在 Windows 10 和 WSL 上测试(Microsoft Ubuntu 16.04.5 LTS):
package main
import (
"fmt"
"net"
)
func localAddresses()
ifaces, err := net.Interfaces()
if err != nil
fmt.Print(fmt.Errorf("localAddresses: %+v\n", err.Error()))
return
for _, i := range ifaces
addrs, err := i.Addrs()
if err != nil
fmt.Print(fmt.Errorf("localAddresses: %+v\n", err.Error()))
continue
for _, a := range addrs
switch v := a.(type)
case *net.IPAddr:
fmt.Printf("%v : %s (%s)\n", i.Name, v, v.IP.DefaultMask())
case *net.IPNet:
fmt.Printf("%v : %s [%v/%v]\n", i.Name, v, v.IP, v.Mask)
func main()
localAddresses()
【讨论】:
【参考方案3】:这应该会给你正在寻找的ipnet
。
ip, ipnet, err := net.ParseCIDR(a.String())
【讨论】:
【参考方案4】:我知道这篇文章适用于 Windows 7,但如果您使用 Mac OS X,希望这对您有所帮助。
只需致电GetNetMask("en0")
func GetNetMask(deviceName string) string
switch runtime.GOOS
case "darwin":
cmd := exec.Command("ipconfig", "getoption", deviceName, "subnet_mask")
out, err := cmd.CombinedOutput()
if err != nil
return ""
nm := strings.Replace(string(out), "\n", "", -1)
log.Println("netmask=", nm, " OS=", runtime.GOOS)
return nm
default:
return ""
return ""
【讨论】:
以上是关于golang 获取本地IP地址的主要内容,如果未能解决你的问题,请参考以下文章