进制对应的英文
name 中文名 含义 举例(以十进制为标准,10的转换)
binary 二进制 满2进1 1010
Octal 八进制 满8进1 12
Decimal 十进制 满10进1 10
Hex 十六进制 满16进1 a
golang中进制之间的相互转换
首先看看go自带的包
“encoding/hex” “encoding/binary”
重点分析 2、10、16进制之间的相互转换
hex 分析
func Encode(dst, src []byte) int {
for i, v := range src {
dst[i*2] = hextable[v>>4]
dst[i*2+1] = hextable[v&0x0f]
}
return len(src) * 2
}
Encode
函数将src目标字节数组,转换成16进制形式的dst字节数组,数组长度翻倍
原理:将原来用一个字节表示的内容,用两个字节来表示,所以返回的dst是src的两倍长度
将原字节右移4位,得到高位内容(ascii码),放在第一个字节,原字节与0000 1111与,得到低位内容(ascii码),放到第二字节
func Decode(dst, src []byte) (int, error) {
var i int
for i = 0; i < len(src)/2; i++ {
a, ok := fromHexChar(src[i*2])
if !ok {
return i, InvalidByteError(src[i*2])
}
b, ok := fromHexChar(src[i*2+1])
if !ok {
return i, InvalidByteError(src[i*2+1])
}
dst[i] = (a << 4) | b
}
if len(src)%2 == 1 {
// Check for invalid char before reporting bad length,
// since the invalid char (if present) is an earlier problem.
if _, ok := fromHexChar(src[i*2]); !ok {
return i, InvalidByteError(src[i*2])
}
return i, ErrLength
}
return i, nil
}
decode
将16进制表达的字节组,还原成10进制表达的字节组
首先分别获取高低位表达的值,将第一个字节,也就是16进制高位的值进行左移4位,左移后的0~3bit就是10进制的前4个bit
将第二个字节,也就是16进制的低位与左移后的值或,得到的字节就是10进制表示的单个字节
最后对16进制的字符串长度进行最后验证,如果长度不正常返回err:odd length hex string
// EncodeToString returns the hexadecimal encoding of src.
func EncodeToString(src []byte) string {
dst := make([]byte, EncodedLen(len(src)))
Encode(dst, src)
return string(dst)
}
此函数是将10进制的数组转成16进制,然后将新的字节组转成ascii码对应的字符串
func DecodeString(s string) ([]byte, error) {
src := []byte(s)
// We can use the source slice itself as the destination
// because the decode loop increments by one and then the 'seen' byte is not used anymore.
n, err := Decode(src, src)
return src[:n], err
}
此函数是将字符串转成16进制形式的字节组,然后再数组转换成10进制形式
其它函数都是encode和decode函数的延伸,就不一一写了。
binary 分析
大小端介绍:通俗来讲,大端就是字节从左向右依次存放高低位,小端就是从左向右依次存放高低位
例子:
将 uint64类型的500存放到字节组中去,500的二进制形式是`0000 0001 1111 0100`
b := make([]byte, 8)
var value uint64 = 500
大端的处理方式:
binary.BigEndian.PutUint64(b, value)
结果
[0,0,0,0,0,1,244]
小端的处理方式:
binary.LittleEndian.PutUint64(b, value)
结果
[244,1,0,0,0,0,0,0]
其它存放函数大同小异,都是将对应bit长度的值存放到对应的字节中,以大端的putuint64为例
func (bigEndian) PutUint64(b []byte, v uint64) {
_ = b[7] // early bounds check to guarantee safety of writes below
b[0] = byte(v >> 56)
b[1] = byte(v >> 48)
b[2] = byte(v >> 40)
b[3] = byte(v >> 32)
b[4] = byte(v >> 24)
b[5] = byte(v >> 16)
b[6] = byte(v >> 8)
b[7] = byte(v)
}
第一个字节存放 48~56bit
第二个字节存放 40~47bit
、
、
、
第八个字节存放 0~7bit