如何在Go中获取本地IP地址?

Jer*_*ain 52 go

我想得到计算机的IP地址.我使用下面的代码,但它返回127.0.0.1.

我想获取IP地址,例如10.32.10.111,而不是环回地址.

name, err := os.Hostname()
if err != nil {
     fmt.Printf("Oops: %v\n", err)
     return
}

addrs, err := net.LookupHost(name)
if err != nil {
    fmt.Printf("Oops: %v\n", err)
    return
}

for _, a := range addrs {
    fmt.Println(a)
}  
Run Code Online (Sandbox Code Playgroud)

Mr.*_*oor 85

当机器上存在多个ip接口时,这是一个更好的解决方案来检索首选的出站IP地址.

import (
    "log"
    "net"
    "strings"
)

// Get preferred outbound ip of this machine
func GetOutboundIP() net.IP {
    conn, err := net.Dial("udp", "8.8.8.8:80")
    if err != nil {
        log.Fatal(err)
    }
    defer conn.Close()

    localAddr := conn.LocalAddr().(*net.UDPAddr)

    return localAddr.IP
}
Run Code Online (Sandbox Code Playgroud)

  • @darkwing它使用的是udp协议,与TCP不同,它没有握手也没有连接.因此,目标不需要在那里,您将收到出站IP. (7认同)
  • 实际上它没有建立任何连接,并且目标根本不需要存在:)所以,代码实际上是什么,如果它将连接到该目标,获取本地地址,您可以更改为任何其他IP你想要的地址.`conn.LocalAddr().String()`是本地ip和端口. (5认同)
  • 我正在寻找同样的东西,这只是一个对我来说很好的:),顺便说一句我想知道你为什么要与谷歌Dns进行udp连接,以及整个"conn.LocalAddr()的价值.字符串( )"? (2认同)
  • 这比公认的解决方案要好。即使您在默认路由网关的子网上有 2 个 IP 地址(比如有线和无线 IP),这(对我来说)也是选择流量将使用的默认 IP。 (2认同)

Seb*_*ian 83

您需要遍历所有网络接口

ifaces, err := net.Interfaces()
// handle err
for _, i := range ifaces {
    addrs, err := i.Addrs()
    // handle err
    for _, addr := range addrs {
        var ip net.IP
        switch v := addr.(type) {
        case *net.IPNet:
                ip = v.IP
        case *net.IPAddr:
                ip = v.IP
        }
        // process IP address
    }
}
Run Code Online (Sandbox Code Playgroud)

播放(取自util/helper.go)

  • @Sebastian您何时期望使用IPAddr而不是IPNet呢? (2认同)

小智 27

为确保获得非环回地址,只需在迭代时检查IP是否为环回.

// GetLocalIP returns the non loopback local IP of the host
func GetLocalIP() string {
    addrs, err := net.InterfaceAddrs()
    if err != nil {
        return ""
    }
    for _, address := range addrs {
        // check the address type and if it is not a loopback the display it
        if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
            if ipnet.IP.To4() != nil {
                return ipnet.IP.String()
            }
        }
    }
    return ""
}
Run Code Online (Sandbox Code Playgroud)

  • 只要只有一个非环回接口可用,这是一个很好的解决方案. (3认同)

Jon*_*art 26

net.LookupHost()os.Hostname()可能总是会给你127.0.0.1,因为那就是你/etc/hosts或同等的东西.

我想你想要用的是net.InterfaceAddrs():

func InterfaceAddrs() ([]Addr, error)

InterfaceAddrs返回系统的网络接口地址列表.


小智 7

这对我有用:

host, _ := os.Hostname()
addrs, _ := net.LookupIP(host)
for _, addr := range addrs {
    if ipv4 := addr.To4(); ipv4 != nil {
        fmt.Println("IPv4: ", ipv4)
    }   
}
Run Code Online (Sandbox Code Playgroud)

与海报的示例不同,它仅返回非环回地址,例如10.120.XX