5

The following grabs the local IP addresses:

package main

import (
    "fmt"
    "net"
)

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

Is this how you would normally get the local IP address, filtering the slice manually according to need?

rino
  • 491
  • 5
  • 12
  • Possible duplicate of [How do I get the local IP address in Go?](https://stackoverflow.com/questions/23558425/how-do-i-get-the-local-ip-address-in-go) – Afriza N. Arief Nov 17 '18 at 15:06

4 Answers4

4

Here's a quick and dirty modification of a code snippet originally 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)

}
photoionized
  • 5,092
  • 20
  • 23
  • 4
    I would say that this link (also from that discussion thread) has shorter and cleaner code to do this: https://github.com/mccoyst/myip/blob/master/myip.go – Timothy Jones Apr 08 '14 at 08:00
  • Ah ok I can see the package methods I need to be using, the second one is nice and brief. – rino Apr 08 '14 at 08:04
  • Agreed. The general idea is essentially the same though, iterate over the ip addresses bound to all interfaces using the net package and filter out any ip address bound to the loopback interface. For a clean implementation I would go with the function that @TimothyJones linked to. – photoionized Apr 08 '14 at 08:04
  • I highly, highly doubt that anyone building an online go interpreter would allow you to enumerate the interfaces on the machine it's running on. Did you try it on your local machine? – photoionized Apr 08 '14 at 17:10
  • @photoionized Yes, originally it did not work on my local machine. I pasted it as http://play.golang.org/p/LGvyWPG7rw just to share the exact code that failed for me locally. – Everton Apr 08 '14 at 18:47
1

Finding the correct IP address can be a problem because a typical server and development machine may have multiple interfaces. For example $ifconfig on my Mac returns the following interfaces lo0, gif0, stf0, en0, en1, en2, bridge0, p2p0, vmnet1, vmnet8, tap0, fw0, en4

Basically, you need to know your environment.

It's not pretty, but for what it's worth, this is what I use on a production Ubuntu server. It also works on my development Mac 10.9.2, who know what it does on 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())
}
tidwall
  • 6,881
  • 2
  • 36
  • 47
1

I have one addition: The current solutions shown above are not working at least on FreeBSD 10 because the system returns the addresses as CIDR notation e.g. 192.168.1.2/32! Therefore, it is necessary to change the solution a little bit:

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

The part ...

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

... detects if / is part of the address and delete this part!

Best regards,

Thorsten

SommerEngineering
  • 1,412
  • 1
  • 20
  • 26
0

These slight modifications worked for me:

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")
}
Everton
  • 12,589
  • 9
  • 47
  • 59