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

Posted

技术标签:

【中文标题】如何在 Go 中获取本地 IP 地址?【英文标题】:How do I get the local IP address in Go? 【发布时间】:2014-06-26 19:52:55 【问题描述】:

我想获取计算机的 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)
  

【问题讨论】:

【参考方案1】:

当机器上存在多个 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

【讨论】:

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

你需要遍历所有网络接口

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
    

Play(取自 util/helper.go)

【讨论】:

谢谢,已将其添加到答案中 util/helper.go 可能是这个 code.google.com/p/whispering-gophers/source/browse/util/… 。 IPv6 怎么样?这似乎只适用于 IPv4 地址。 对 net.Interfaces() 的调用在我的 Linux 主机(Manjaro,当前)上没有返回错误和 0 个接口play.golang.org/p/0K5bL_eqFm :(【参考方案3】:

为确保您获得非环回地址,只需在迭代时检查 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 ""

【讨论】:

这是一个很好的解决方案,只要只有一个非环回接口可用。【参考方案4】:

您的os.Hostname() 上的net.LookupHost() 可能总是会给您127.0.0.1,因为那是您的/etc/hosts 或等效项中的内容。

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

func InterfaceAddrs() ([]Addr, error)

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

【讨论】:

这有它自己的皱纹。地址以字符串形式提供。给定一个 IP 地址(特定的 Go 类型,而不是通用术语),没有直接的比较。要么需要将 IP 转换为字符串并进行比较,要么解析字符串以获取要比较的 IP,对于这个新手 Go 程序员来说,这两者都不是微不足道的。我正在寻找将字符串转换为 IP 的库程序,但还没有找到。 你指的Go类型的IP地址是什么? golang.org/pkg/net/#IP type IP []byte 我寻找的解析器就在页面下方: func ParseCIDR(s string) (IP, *IPNet, error) (似乎无法格式化这些行作为代码。)【参考方案5】:

这对我有用:

host, _ := os.Hostname()
addrs, _ := net.LookupIP(host)
for _, addr := range addrs 
    if ipv4 := addr.To4(); ipv4 != nil 
        fmt.Println("IPv4: ", ipv4)
       

与发布者的示例不同,它仅返回非环回地址,例如10.120.X.X.

【讨论】:

但如果我使用 if 循环,它将是该循环内的本地...我想在此循环外使用 ipv4 值 @VijayKumar, var ipv4 net.IP 在循环之外使用ipv4 = addr.To4()(而不是ipv4 := addr.To4()【参考方案6】:
func GetInternalIP() string 
    itf, _ := net.InterfaceByName("enp1s0") //here your interface
    item, _ := itf.Addrs()
    var ip net.IP
    for _, addr := range item 
        switch v := addr.(type) 
        case *net.IPNet:
            if !v.IP.IsLoopback() 
                if v.IP.To4() != nil //Verify if IP is IPV4
                    ip = v.IP
                
            
        
    
    if ip != nil 
        return ip.String()
     else 
        return ""
    

【讨论】:

【参考方案7】:
func resolveHostIp() (string) 

    netInterfaceAddresses, err := net.InterfaceAddrs()

    if err != nil  return "" 

    for _, netInterfaceAddress := range netInterfaceAddresses 

        networkIp, ok := netInterfaceAddress.(*net.IPNet)

        if ok && !networkIp.IP.IsLoopback() && networkIp.IP.To4() != nil 

            ip := networkIp.IP.String()

            fmt.Println("Resolved Host IP: " + ip)

            return ip
        
    
    return ""

【讨论】:

【参考方案8】:

如果你只有一个 IP 地址,除了 127.0.0.1,你可以在这里查看代码。

conn,err := net.Dial("ip:icmp","google.com")
fmt.Println(conn.LocalAddr())

第二个参数可以是除127.0.0.1以外的任何IP地址

【讨论】:

您能否详细说明这与***.com/a/37382208/916440 有何不同?谢谢。

以上是关于如何在 Go 中获取本地 IP 地址?的主要内容,如果未能解决你的问题,请参考以下文章

如何获取本地计算机的 IP 地址?

如何在 Oracle ApEx 中获取 PC 的本地 IP 地址

怎样用go语言获取本地IP地址

如何获取本地IP地址python?

如何在 Unix 套接字编程中获取本地 IP 地址和端口?

如何在网络上自动获取本地IP地址及其原理