【问题标题】:How do I get the local IP address in Go?如何在 Go 中获取本地 IP 地址?
【发布时间】: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)
}  

【问题讨论】:

    标签: go


    【解决方案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)

    【讨论】:

    【解决方案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地址

        【讨论】:

        猜你喜欢
        • 2012-05-31
        • 2021-01-28
        • 2011-10-11
        • 1970-01-01
        • 2015-07-09
        • 2012-11-29
        • 2011-04-08
        相关资源
        最近更新 更多