IP address type

The package "net" defines many types, functions and methods of use in Go network programming. The type IP is defined as byte slices

  1. type IP []byte

There are several functions to manipulate a variable of type IP, but you are likely to use only some of them in practice.
For example, the function ParseIP(String) will take a dotted IPv4 address or a colon IPv6 address, while the IP method String will return a string.
Note that you may not get back what you started with: the string form of 0:0:0:0:0:0:0:1 is ::1.

A program to illustrate this is

  1. /* IP
  2. */
  3. package main
  4. import (
  5. "net"
  6. "os"
  7. "fmt"
  8. )
  9. func main() {
  10. if len(os.Args) != 2 {
  11. fmt.Fprintf(os.Stderr, "Usage: %s ip-addr\n", os.Args[0])
  12. os.Exit(1)
  13. }
  14. name := os.Args[1]
  15. addr := net.ParseIP(name)
  16. if addr == nil {
  17. fmt.Println("Invalid address")
  18. } else {
  19. fmt.Println("The address is ", addr.String())
  20. }
  21. os.Exit(0)
  22. }

If this is compiled to the executable IP then it can run for example as

  1. IP 127.0.0.1

with response

  1. The address is 127.0.0.1

or as

  1. IP 0:0:0:0:0:0:0:1

with response

  1. The address is ::1

The type IPmask

In order to handle masking operations, there is the type

  1. type IPMask []byte

There is a function to create a mask from a 4-byte IPv4 address

  1. func IPv4Mask(a, b, c, d byte) IPMask

Alternatively, there is a method of IP which returns the default mask

  1. func (ip IP) DefaultMask() IPMask

Note that the string form of a mask is a hex number such as ffff0000 for a mask of 255.255.0.0.

A mask can then be used by a method of an IP address to find the network for that IP address

  1. func (ip IP) Mask(mask IPMask) IP

An example of the use of this is the following program:

  1. /* Mask
  2. */
  3. package main
  4. import (
  5. "fmt"
  6. "net"
  7. "os"
  8. )
  9. func main() {
  10. if len(os.Args) != 2 {
  11. fmt.Fprintf(os.Stderr, "Usage: %s dotted-ip-addr\n", os.Args[0])
  12. os.Exit(1)
  13. }
  14. dotAddr := os.Args[1]
  15. addr := net.ParseIP(dotAddr)
  16. if addr == nil {
  17. fmt.Println("Invalid address")
  18. os.Exit(1)
  19. }
  20. mask := addr.DefaultMask()
  21. network := addr.Mask(mask)
  22. ones, bits := mask.Size()
  23. fmt.Println("Address is ", addr.String(),
  24. " Default mask length is ", bits,
  25. "Leading ones count is ", ones,
  26. "Mask is (hex) ", mask.String(),
  27. " Network is ", network.String())
  28. os.Exit(0)
  29. }

If this is compiled to Mask and run by

  1. Mask 127.0.0.1

it will return

  1. Address is 127.0.0.1 Default mask length is 8 Network is 127.0.0.0

The type IPAddr

Many of the other functions and methods in the net package return a pointer to an IPAddr.
This is simply a structure containing an IP.

  1. type IPAddr {
  2. IP IP
  3. }

A primary use of this type is to perform DNS lookups on IP host names.

  1. func ResolveIPAddr(net, addr string) (*IPAddr, os.Error)

where net is one of "ip", "ip4" or "ip6". This is shown in the program

  1. /* ResolveIP
  2. */
  3. package main
  4. import (
  5. "net"
  6. "os"
  7. "fmt"
  8. )
  9. func main() {
  10. if len(os.Args) != 2 {
  11. fmt.Fprintf(os.Stderr, "Usage: %s hostname\n", os.Args[0])
  12. fmt.Println("Usage: ", os.Args[0], "hostname")
  13. os.Exit(1)
  14. }
  15. name := os.Args[1]
  16. addr, err := net.ResolveIPAddr("ip", name)
  17. if err != nil {
  18. fmt.Println("Resolution error", err.Error())
  19. os.Exit(1)
  20. }
  21. fmt.Println("Resolved address is ", addr.String())
  22. os.Exit(0)
  23. }

Running ResolveIP www.google.com returns

  1. Resolved address is 66.102.11.104

Host lookup

The function ResolveIPAddr will perform a DNS lookup on a hostname, and return a single IP address.
However, hosts may have multiple IP addresses, usually from multiple network interface cards. They may also have multiple host names, acting as aliases.

  1. func LookupHost(name string) (addrs []string, err os.Error)

One of these addresses will be labelled as the “canonical” host name. If you wish to find the canonical name, use

  1. func LookupCNAME(name string) (cname string, err os.Error)

This is shown in the following program

  1. /* LookupHost
  2. */
  3. package main
  4. import (
  5. "net"
  6. "os"
  7. "fmt"
  8. )
  9. func main() {
  10. if len(os.Args) != 2 {
  11. fmt.Fprintf(os.Stderr, "Usage: %s hostname\n", os.Args[0])
  12. os.Exit(1)
  13. }
  14. name := os.Args[1]
  15. addrs, err := net.LookupHost(name)
  16. if err != nil {
  17. fmt.Println("Error: ", err.Error())
  18. os.Exit(2)
  19. }
  20. for _, s := range addrs {
  21. fmt.Println(s)
  22. }
  23. os.Exit(0)
  24. }

Note that this function returns strings, not IPAddress values.