【问题标题】:How to retrieve address of current machine?如何检索当前机器的地址?
【发布时间】:2014-05-20 18:20:09
【问题描述】:

以下抓取本地IP地址:

package main

import (
    "fmt"
    "net"
)

func main() {
    a, _ := net.LookupHost("localhost")
    fmt.Printf("Addresses: %#+v\n",a)
}

这是您通常获取本地 IP 地址并根据需要手动过滤切片的方式吗?

【问题讨论】:

标签: go


【解决方案1】:

这是对代码 sn-p 的快速而肮脏的修改,最初是 posted by Russ Cox to the golang-nuts google group

package main

import (
  "fmt" 
  "net" 
  "os"  
)

func main() {
  tt, err := net.Interfaces()
  if err != nil { 
    panic(err)  
  }     
  for _, t := range tt {
    aa, err := t.Addrs()
    if err != nil {
      panic(err)        
    }           
    for _, a := range aa {
      ipnet, ok := a.(*net.IPNet) 
      if !ok {          
        continue                
      }                 
      v4 := ipnet.IP.To4() 
      if v4 == nil || v4[0] == 127 { // loopback address
        continue                
      }                 
      fmt.Printf("%v\n", v4)
    }           
    os.Exit(0)  
  }     
  os.Exit(1)

}

【讨论】:

  • 我会说这个链接(也来自那个讨论线程)有更短和更清晰的代码来做到这一点:github.com/mccoyst/myip/blob/master/myip.go
  • 啊好的我可以看到我需要使用的封装方法,第二个很好而且简短。
  • 同意。总体思路基本相同,使用 net 包遍历绑定到所有接口的 IP 地址,并过滤掉绑定到环回接口的任何 IP 地址。对于一个干净的实现,我会使用@TimothyJones 链接到的函数。
  • 我非常非常怀疑任何构建在线 Go 解释器的人都会允许您枚举运行它的机器上的接口。你在本地机器上试过了吗?
  • @photoionized 是的,最初它在我的本地机器上不起作用。我将其粘贴为 play.golang.org/p/LGvyWPG7rw 只是为了分享我在本地失败的确切代码。
【解决方案2】:

查找正确的 IP 地址可能是个问题,因为典型的服务器和开发机器可能有多个接口。例如我 Mac 上的 $ifconfig 返回以下接口 lo0, gif0, stf0, en0, en1, en2, bridge0, p2p0, vmnet1, vmnet8, tap0, fw0, en4

基本上,您需要了解您的环境。

它并不漂亮,但值得一提的是,这是我在生产 Ubuntu 服务器上使用的。它也适用于我的开发 Mac 10.9.2,谁知道它在 Windows 上的作用。

package main

import (
    "net"
    "strings"
)

func findIPAddress() string {
    if interfaces, err := net.Interfaces(); err == nil {
        for _, interfac := range interfaces {
            if interfac.HardwareAddr.String() != "" {
                if strings.Index(interfac.Name, "en") == 0 ||
                    strings.Index(interfac.Name, "eth") == 0 {
                    if addrs, err := interfac.Addrs(); err == nil {
                        for _, addr := range addrs {
                            if addr.Network() == "ip+net" {
                                pr := strings.Split(addr.String(), "/")
                                if len(pr) == 2 && len(strings.Split(pr[0], ".")) == 4 {
                                    return pr[0]
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    return ""
}

func main() {
    println(findIPAddress())
}

【讨论】:

    【解决方案3】:

    我有一个补充:上面显示的当前解决方案至少在 FreeBSD 10 上不起作用,因为系统将地址作为 CIDR 表示法返回,例如192.168.1.2/32!因此,有必要稍微改变一下解决方案:

    package main
    
    import (
        "fmt"
        "net"
        "os"
        "strings"
    )
    
    func main() {
        addrs, err := net.InterfaceAddrs()
        if err != nil {
            fmt.Println("Error: " + err.Error())
            os.Exit(1)
        }
    
        for _, a := range addrs {
            text := a.String()
    
            if strings.Contains(text, `/`) {
                text = text[:strings.Index(text, `/`)]
            }
    
            ip := net.ParseIP(text)
            if !ip.IsLoopback() && !ip.IsUnspecified() {
                fmt.Println(ip)
            }
        }
    }
    

    部分...

    if strings.Contains(text, `/`) {
        text = text[:strings.Index(text, `/`)]
    }
    

    ...检测/是否是地址的一部分并删除这部分!

    最好的问候,

    索斯滕

    【讨论】:

      【解决方案4】:

      这些细微的修改对我有用:

      package main
      
      import (
          "fmt"
          "net"
          "os"
      )
      
      func myip() {
          os.Stdout.WriteString("myip:\n")
      
          addrs, err := net.InterfaceAddrs()
          if err != nil {
              fmt.Errorf("error: %v\n", err.Error())
              return
          }
      
          for _, a := range addrs {
              ip := net.ParseIP(a.String())
              fmt.Printf("addr: %v loopback=%v\n", a, ip.IsLoopback())
          }
      
          fmt.Println()
      }
      
      func myip2() {
          os.Stdout.WriteString("myip2:\n")
      
          tt, err := net.Interfaces()
          if err != nil {
              fmt.Errorf("error: %v\n", err.Error())
              return
          }
          for _, t := range tt {
              aa, err := t.Addrs()
              if err != nil {
                  fmt.Errorf("error: %v\n", err.Error())
                  continue
              }
              for _, a := range aa {
                  ip := net.ParseIP(a.String())
                  fmt.Printf("%v addr: %v loopback=%v\n", t.Name, a, ip.IsLoopback())
              }
          }
      
          fmt.Println()
      }
      
      func main() {
          fmt.Println("myip -- begin")
          myip()
          myip2()
          fmt.Println("myip -- end")
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-01-14
        • 2012-03-17
        • 2015-11-17
        • 2013-04-29
        • 1970-01-01
        • 2010-12-05
        相关资源
        最近更新 更多