简言
今天看nsq的messageID生成的时候,发现它使用了hex.Encode函数来产生编码,那就顺道研究一下这个编码方式。
原理
hex是16进制的意思,encode是进行编码的意思,内部实现也很简单,就是
每4位计算出十六进制的值,因为4位二进制范围0000 ~ 1111,也就是在0~15之间,用16进制来表示即0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f 取这些字符对应的ASCII码的二进制即可
而且,大家如果按照16进制来显示这些转换后的字节数组,会发现范围都是在0~9 a~f
很明显这种把1个字节分两步,按照每4位来转换成1个字节,最终形成2个字节的方式,相比原来,编码结果是翻倍
举例:原本有1个字节的内容是 00010111,现在进行hex.Encode操作
先把前面的0001计算出十六进制,也就是1,字符1对应的ASCII码表中是0011 0001
再把后面的0111计算出十六进制,也就是7,字符7对应的ASCII码表中是0011 0111
一通操作下来,原来一个字节就变成了两个字节
hex.Encode就是遍历给定的字节数组,把每个字节都这样处理
我们再举个代码的例子(对4个字节进行Encode,会发现得到了8个字节)
package main
import ("encoding/hex""fmt"
)
func main() {// 原来的字节数组,4字节src := []byte{1, 11, 226, 'H'}// 结果的字节数组,其实8字节就够,这里特意搞了10个字节,大家会发现后面两个字节没变dest := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}hex.Encode(dest, src)for i := 0; i < len(dest); i++ {fmt.Printf("dest[%d]=%v \n", i, dest[i])}
}
运行结果如下图
先给大家贴出来ASCII码表
贴出来源字符串
src := []byte{1, 11, 226, 'H'}
解释下上面代码的转换过程
第一个字节,src中是1,二进0000 0001,转换过程如下
高4位的0000计算出十六进制的值,也就是0,在ASCII码表中字符0对应48
低4位的0001计算出十六进制的值,也就是1,在ASCII码表中字符1对应49
第二个字节,src中是11,二进制0000 1011,转换过程如下
高4位的0000计算出十六进制的值,也就是0,在ASCII码表中字符0对应48
低4位的1011计算出十六进制的值,也就是b,在ASCII码表中字符b对应98
第三个字节,src中是226,二进制1110 0010,转换过程如下
高4位的1110计算出十六进制的值,也就是e,在ASCII码表中字符e对应101
低4位的0010计算出十六进制的值,也就是2,在ASCII码表中字符2对应50
第四个字节,src中是'H',二进制0100 1000,转换过程如下
高4位的0100计算出十六进制的值,也就是4,在ASCII码表中字符4对应52
低4位的1000计算出十六进制的值,也就是8,在ASCII码表中字符8对应56