与大多数语言一样,Go的标准库很全,因为Go的出现本来就是为了网络通信的高并发实现,所以其相关的网络库封装得更简洁,更Readable。

net.ResolveIPAddr()

       根据域名查找IP地址

       不得不感叹Go为开发者考虑良多,godoc这个工具真的很方便!先看下源码。

$ godoc -src net.ResolveIPAddr
func ResolveIPAddr(net, addr string) (*IPAddr, error) {
    if net == "" {
        net = "ip"
    }
    afnet, _, err := parseNetwork(net)
    if err != nil {
        return nil, err
    }
    switch afnet {
    case "ip", "ip4", "ip6":
    default:
        return nil, UnknownNetworkError(net)
    }
    addrs, err := internetAddrList(afnet, addr, noDeadline)
    if err != nil {
        return nil, err
    }
    return addrs.first(isIPv4).(*IPAddr), nil
}
case "ip", "ip4", "ip6"

       可以看到,net和addr形参都接受string类型,而返回IPAddr的指针类型,和error类型的值。

       来使用一下:

package main

import (
    "fmt"
    "net"
)

func main() {
    addr, err := net.ResolveIPAddr("ip", "www.baidu.com")
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
    fmt.Println(addr.IP)

       输出:
这里写图片描述

ResolveIPAddrUnknownNetworkError(net)unknown network tcp
net.ParseIP()

       检查IP地址格式是否有效

$ godoc -src net ParseIP
func ParseIP(s string) IP {
    for i := 0; i < len(s); i++ {
        switch s[i] {
        case '.':
            return parseIPv4(s)
        case ':':
            ip, _ := parseIPv6(s, false)
            return ip
        }
    }
    return nil
}
.:
net.parseIPv4net.parseIPv6
cannot refer to unexported name net.parseIPV4
undefined: net.parseIPV4

       因为Go利用首字母的大小写来限制包外是否可访问,小写的函数或变量在包外无法访问到,就如同Java的public,private修饰符。不过用godoc来获取小写开头的源码是没有问题的。

       查看parseIPv4的源码又发现:

func parseIPv4(s string) IP {
    // ...
    return IPv4(p[0], p[1], p[2], p[3])
}

       再追溯到IPv4上

func IPv4(a, b, c, d byte) IP {
    p := make(IP, IPv6len)
    copy(p, v4InV6Prefix)
    p[12] = a
    p[13] = b
    p[14] = c
    p[15] = d
    return p
}

       我们发现这些函数都返回了IP对象,我们来看一下IP对象的定义:

type IP []byte 

       其实就是一个自定义的数组切片类型。

       IPv4内部用make初始化了一个数组切片,并且指定了元素个数为IPv6len。IPv6len被定义为常量:

const (
    IPv6len = 16
)

       然后进行将v4InV6Prefix复制到到数组切片p中,copy的用法请自行搜索(注意copy的行为和常人的理解不同):

var v4InV6Prefix = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff}
type IP []byte
// An IP is a single IP address, a slice of bytes.
// Functions in this package accept either 4-byte (IPv4)
// or 16-byte (IPv6) slices as input.
//
// Note that in this documentation, referring to an
// IP address as an IPv4 address or an IPv6 address
// is a semantic property of the address, not just the
// length of the byte slice: a 16-byte slice can still
// be an IPv4 address.
type IP []byte
slice1 := make([]int, 5)

       Go的源码不难,甚至比C简单,而且标准库的设计也非常规范。如果你需要使用更多的功能,可以查看net包的文档。