golang ipv4/6 与长整型 bigint的 转换实现
import (
"encoding/hex"
"errors"
"fmt"
"math/big"
"net"
"regexp"
"strconv"
"strings"
)
// 0: invalid ip
// 4: IPv4
// 6: IPv6
// 检查IP 用于 net.ParseIP(ipv4)
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
}
// IPv4ByLong
// 将 uint32 长整型转换成IPV4 地址
// converts a uint32 represented by a string into an ipv4 address string
// 168427779 => "10.10.1.2"
func IPv4ByLong(ipv4long string) (string, error) {
ipv4Int, err := strconv.ParseInt(ipv4long, 10, 64)
if err != nil {
return "", errors.New(fmt.Sprintf("fail to convert string to Int64 :%s", err.Error()))
}
ipv4 := uint32(ipv4Int)
return fmt.Sprintf("%d.%d.%d.%d", ipv4>>24, ipv4<<8>>24, ipv4<<16>>24, ipv4<<24>>24), nil
}
// IPv6ByLong
// 将 big.Int 长整型转换成IPV6 地址
// converts a big integer represented by a string into an IPv6 address string
// 53174336768213711679990085974688268287=> "2801:0137:0000:0000:0000:ffff:ffff:ffff"
func IPv6ByLong(ipv6long string) (string, error) {
bi, ok := new(big.Int).SetString(ipv6long, 10)
if !ok {
return "", errors.New("fail to convert string to big.Int")
}
b255 := new(big.Int).SetBytes([]byte{255})
var buf = make([]byte, 2)
p := make([]string, 8)
j := 0
var i uint
tmpint := new(big.Int)
for i = 0; i < 16; i += 2 {
tmpint.Rsh(bi, 120-i*8).And(tmpint, b255)
bytes := tmpint.Bytes()
if len(bytes) > 0 {
buf[0] = bytes[0]
} else {
buf[0] = 0
}
tmpint.Rsh(bi, 120-(i+1)*8).And(tmpint, b255)
bytes = tmpint.Bytes()
if len(bytes) > 0 {
buf[1] = bytes[0]
} else {
buf[1] = 0
}
p[j] = hex.EncodeToString(buf)
j++
}
return strings.Join(p, ":"), nil
}
// 将IPV4 转换成 uint32 长整型
func IPv4ToInt(ipv4 string) (ip uint32) {
r := `^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})`
reg, err := regexp.Compile(r)
if err != nil {
return 0
}
ips := reg.FindStringSubmatch(ipv4)
if ips == nil {
return 0
}
//上面正则做了判断,这里就不报错了
ip1, _ := strconv.Atoi(ips[1])
ip2, _ := strconv.Atoi(ips[2])
ip3, _ := strconv.Atoi(ips[3])
ip4, _ := strconv.Atoi(ips[4])
if ip1 > 255 || ip2 > 255 || ip3 > 255 || ip4 > 255 {
return 0
}
ip += uint32(ip1 * 0x1000000) // 左移24位
ip += uint32(ip2 * 0x10000) // 左移16位
ip += uint32(ip3 * 0x100) // 左移8位
ip += uint32(ip4) // 左移0位
return ip
}
// 将IPV6 转换成 big.Int 长整型
func IPv6ToInt(ipv6 string) (*big.Int, error) {
ip := net.ParseIP(ipv6)
return NetIpv6ToInt(ip)
}
// 将net.IP 类型 转换成 big.Int 长整型
func NetIpv6ToInt(ip net.IP) (*big.Int, error) {
if ip == nil {
return nil, errors.New("invalid ipv6")
}
IPv6Int := big.NewInt(0)
IPv6Int.SetBytes(ip)
return IPv6Int, nil
}