golang 获取本地IP地址

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了golang 获取本地IP地址相关的知识,希望对你有一定的参考价值。

Use net.InterfaceAddrs().

addrs, err := net.InterfaceAddrs()
if err != nil {
    panic(err)
}   
for i, addr := range addrs {
    fmt.Printf("%d %v\n", i, addr)
}   
If you want to know interface names too, use net.Interfaces() to get a list of interfaces first.

list, err := net.Interfaces()
if err != nil {
    panic(err)
}   

for i, iface := range list {
    fmt.Printf("%d name=%s %v\n", i, iface.Name, iface)
    addrs, err := iface.Addrs()
    if err != nil {
        panic(err)
    }
    for j, addr := range addrs {
        fmt.Printf(" %d %v\n", j, addr)
    }
}
#pkg~net

如何从本地接口获取所有地址和掩码?

【中文标题】如何从本地接口获取所有地址和掩码?【英文标题】: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地址的主要内容,如果未能解决你的问题,请参考以下文章

编程实践Golang 获取HTTP请求的IP地址

如何从本地接口获取所有地址和掩码?

golang 使用一个命令获取您的公共和私有IP地址

如何在Node.js中获取本机本地IP地址

我的本地连接现在“网络未分配网络地址 ”,点击修复“无法续订ip地址”

js 怎么获取本地ip\