ProtoBuffer Encoding 原理解析
本文参考官方的 Encoding 文档
https://developers.google.com/protocol-buffers/docs/encoding
准备工作
下载 proto 相关工具 https://developers.google.com/protocol-buffers
准备测试用的 proto 文件 test.proto
package main;
message PB_ProtoBufEncodingTest
{
optional int32 id = 1;
optional string name = 2;
optional string address = 3;
optional int64 number = 4;
}
用官方提供的工具生成 go 代码
protoc.exe --go_out=./ ./test.proto
然后打印几条简单信息的二进制数据和16进制数据:
package main
import (
"code.google.com/p/goprotobuf/proto"
"fmt"
)
func main() {
test := &PB_ProtoBufEncodingTest{
Id: proto.Int32(150),
}
out, _ := proto.Marshal(test)
for i, _ := range out {
fmt.Printf("%02X ", out[i])
//08 96 01
}
fmt.Println()
for i, _ := range out {
fmt.Printf("%08b ", out[i])
//00001000 10010110 00000001
}
}
Base 128 Varints 编码
本文先从整型数据的编码开始讲起, proto 的高压缩比很大一部分来源于对数值类型的压缩。而在一切开始之前,先介绍下整型数据的一种常用编码方式: varints。
Varints 是一种使用变长字节来序列化整数的方法,数值越小,占用的字节数越少。那么如何识别一个整数的边界呢?答案是用每个字节的第一位,如果连续的字节表示的是同一个整数,那么除了最后一个字节之外的,前面的字节的最高位都置 1 ,每当遇到的最高位非 1 的字节,即表示与之前连续最高位为1 的字节加起来表示一个整数。由于最高位的存在,每个字节实际存储数据的位只有7位,因此也叫 Base 128 。
对于 300 来说