Go语言:判断IP是否合法是IPv4还是IPv6

net.IP的ParseIP函数判断IPv4/IPv6的依据就是是否出现".”或者":",因为返回的net.IP都是16字节,而且IPv4前面加了::ffff所以根据返回的IP是不太好判断输入的原始字符串是IPv4还是IPv6。所以得自己写,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package main

import (
    "fmt"
    "net"
)

// 0: invalid ip
// 4: IPv4
// 6: IPv6
func ParseIP(s string) (net.IP, int) {
    ip := net.ParseIP(s)
    if ip == nil {
        return nil, 0
    }
    for i := 0; i < len(s); i++ {
        switch s[i] {
        case '.':
            return ip, 4
        case ':':
            return ip, 6
        }
    }
    return nil, 0
}

func test(s string) {
    ip, n := ParseIP(s)
    fmt.Printf("%v %v\n", n, ip)
}
func main() {
    test("127.0.0.1")
    test("::127.0.0.1")
    test("2001:0:53ab:0:0:0:0:0")
    test("2001:0:c38c:ffff:ffff:0000:0000:ffff")
    test("2001:0:c38c:ffff:ffff::")
    test("327.0.0.1")
    test("2001:0:c38c:ffff:ffff:ffff:ffff:ffff1")
}

输出:

1
2
3
4
5
6
7
4 127.0.0.1
6 ::7f00:1
6 2001:0:53ab::
6 2001:0:c38c:ffff:ffff::ffff
6 2001:0:c38c:ffff:ffff::
0 <nil>
0 <nil>

net.IP源码:

1
2
3
4
5
6
7
8
9
10
11
func ParseIP(s string) IP {
    for i := 0; i < len(s); i++ {
        switch s[i] {
        case '.':
            return parseIPv4(s)
        case ':':
            return parseIPv6(s)
        }
    }
    return nil
}