一、文章
https://zhuanlan.zhihu.com/p/404782892
二、测试
1.test.proto
syntax = "proto3";
package proto;
option go_package = "./;proto";
message Msg{
uint32 age1 = 1;
sint32 age2 = 2;
string name = 3;
bytes data = 4;
}
2.main.go
package main
import (
"fmt"
pb "test/proto"
"google.golang.org/protobuf/proto"
)
func main() {
{
m := pb.Msg{Age1: 5, Age2: -5, Name: "aaa", Data: []byte("111我")}
d, err := proto.Marshal(&m)
if err != nil {
return
}
fmt.Println(fmt.Sprintf("%08b", d))
}
fmt.Printf("%08b\n", []byte("我"))
}
3.结果:
4.分析:
由于protobuf编码后由 key-value组成
则:
age1为 00001000 00000101
其中:
00001000 = 1 << 3 | 0,
00000101 就是5的varint编码;
age2为 00010000 00001001
其中:
00010000 = 2 << 3 | 0
00001001 是-5经过zigzag编码->varint编码的结果
name为 00011010 00000010 01100001 01100001
其中:
00011010 = 3 << 3 | 2
00000010代表长度2
01100001就是字符a的AISCII编码97
data为 00100010 00000101 00110001 00110001 11100110 10001000 10010001
其中:
00100010 = 4 << 3 | 2
00000101代表长度5
01100001就是字符a的AISCII编码97
11100110 10001000 10010001 就是‘我’。
由fmt.Printf("%08b\n", []byte("我"))可以得到‘我’的二进制编码。
得出一下结论:
1.protobuf不会对string,bytes进行压缩,按照内存中的格式进行传输。
2.protobuf会对数字进行压缩传输,注意使用负数时,应使用sint32、sint64。
3.protobuf不像json,xml一样传输字段,而是传输字段在结构中的序号。