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


69

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

Answers:


117

您需要遍历所有网络接口

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
    }
}

播放(取自util / helper.go)


谢谢,将其添加到答案中
塞巴斯蒂安

1
util / helper.go可能是此code.google.com/p/whispering-gophers/source/browse/util/…。IPv6呢?这似乎仅适用于IPv4地址。

1
对net.Interfaces()的调用没有返回错误,并且在我的Linux主机(Manjaro,当前)上的0接口上不返回错误。play.golang.org
p/

1
@塞巴斯蒂安(Sebastian)我用手指在手机上投票,不小心给了你一张反对票,对不起。如果您进行了琐碎的编辑,我会解决的。 meta.stackexchange.com/questions/69044/...
Cawb07

2
@Sebastian您什么时候会想到这种IPAddr情况而不是这种IPNet情况?
利亚姆·凯利

115

当计算机上存在多个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
}

2
我一直在寻找相同的东西,而这对我来说只是一个很好的方法:),顺便说一句,我想知道为什么您要与Google Dns建立udp连接,以及“ conn.LocalAddr()。String()的整个值是什么? )”?
StackB00m,

7
实际上,它不建立任何连接,并且目的地根本不需要存在:)因此,代码的实际作用是,如果它将连接到该目标,则获取本地up地址,您可以更改为任何其他IP您想要的地址。 conn.LocalAddr().String()是本地IP和端口。
“隔壁”的

1
这比公认的解决方案好。即使您在默认路由网关的子网中有2个IP地址(例如,有线和无线IP),这(对我而言)仍在选择通信将使用的默认IP。
dimalinux '17

8
@darkwing它使用的是udp协议,与TCP不同,它没有握手或连接。因此,目标不需要存在,您将收到出站IP。
“隔壁”的

1
@darkwing:将其视为“逻辑”连接,而不是“物理”连接。
ereOn

35

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

6
只要只有一个非环回接口可用,这是一个很好的解决方案。
玛丽安

26

net.LookupHost()在您os.Hostname()身上可能总是会给您127.0.0.1,因为这就是您/etc/hosts或同等水平的东西。

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

func InterfaceAddrs() ([]Addr, error)

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


这有它自己的皱纹。地址以字符串形式提供。给定IP地址(特定的Go类型,而不是通用术语),则没有直接比较。有必要将IP转换为字符串,然后比较或解析字符串以使IP进行比较,这对于这个新手Go程序员来说都不是小事。我正在寻找将字符串转换为IP的库过程,但尚未找到。
HankB

您指的IP地址转到类型是什么?
乔纳森·莱因哈特

golang.org/pkg/net/#IP 类型IP [] byte并且我要寻找的解析器正好在页面上以下:func ParseCIDR(s string)(IP,* IPNet,error)(似乎无法将这些行格式化为码)。
HankB

12

这对我有用:

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

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


但是如果我使用if循环,它将在该循环内是局部的...我想在该循环外使用ipv4值
Vijay Kumar 2015年

2
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 ""
}

1
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 ""
    }
}

0

如果除127.0.0.1之外只有一个IP地址,则可以在此处查看代码。

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.