【Go】IP地址轉換:數字與字符串之間高效轉換


轉載:https://blog.thinkeridea.com/201903/go/ip2long.html

IP 地址庫中 IP 地址的保存格式一般有兩種,一種是點分十進制形式(192.168.1.1),另一種是數字形式(3232235777),應用中,經常需要在這兩種格式之間做轉換。

針對這一個問題我在 exnet 擴展包里面實現可兩者的轉換的快捷方法:

  • func IP2Long(ip net.IP) (uint, error) IP2Long 把 net.IP 轉為數值
  • func Long2IP(i uint) (net.IP, error) Long2IP 把數值轉為 net.IP
  • func IPString2Long(ip string) (uint, error) IPString2Long 把 ip 字符串轉為數值
  • func Long2IPString(i uint) (string, error) Long2IPString 把數值轉為 ip 字符串

使用示例:

package main

import (
	"fmt"
	"net"
	"reflect"

	"github.com/thinkeridea/go-extend/exnet"
)

func main() {
	ip := "192.168.1.1"

	n, _ := exnet.IPString2Long(ip)
	s, _ := exnet.Long2IPString(n)

	fmt.Println(n, s == ip)

	Ip1 := net.ParseIP(ip) // 會得到一個16字節的byte,主要為了兼容ipv6
	n, _ = exnet.IP2Long(Ip1)

	Ip2, _ := exnet.Long2IP(n)

	fmt.Println(n, reflect.DeepEqual(Ip1[12:], Ip2))
}

那么是如何將點分十進制的IP地址轉為數字?

IPv4 地址有4個字節,樣式如下:

MSB————–LSB

b4 b3 b2 b1

每個字節表示的范圍:

  • byte4: 4294967296(1<<32)
  • byte3: 16777216(1<<24)
  • byte2: 65536(1<<16)
  • byte1: 256(1<<8)

通用公式:b4<<24 | b3<<16 | b2<<16 | b1

例如,222.173.108.86

轉換方法:222<<24 | 173<<16 | 108<<8 | 86 = 3735907414

再例如,1.0.1.1

轉換方法:1<<24 | 0<<16 | 1<<8 | 1 = 16777473

exnet 中實現如下:

// IPString2Long 把ip字符串轉為數值
func IPString2Long(ip string) (uint, error) {
	b := net.ParseIP(ip).To4()
	if b == nil {
		return 0, errors.New("invalid ipv4 format")
	}

	return uint(b[3]) | uint(b[2])<<8 | uint(b[1])<<16 | uint(b[0])<<24, nil
}

把數值轉換為字符串的邏輯翻轉過來即可, exnet 中實現如下:

// Long2IPString 把數值轉為ip字符串
func Long2IPString(i uint) (string, error) {
	if i > math.MaxUint32 {
		return "", errors.New("beyond the scope of ipv4")
	}

	ip := make(net.IP, net.IPv4len)
	ip[0] = byte(i >> 24)
	ip[1] = byte(i >> 16)
	ip[2] = byte(i >> 8)
	ip[3] = byte(i)

	return ip.String(), nil
}

轉載:

本文作者: 戚銀(thinkeridea

本文鏈接: https://blog.thinkeridea.com/201903/go/ip2long.html

版權聲明: 本博客所有文章除特別聲明外,均采用 CC BY 4.0 CN協議 許可協議。轉載請注明出處!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM