Protocol Buffers 是一种与语言、平台无关,可扩展的序列化结构化数据的方法,常用于通信协议,数据存储等等。相较于 JSON、XML,它更小、更快、更简单,因此也更受开发人员的青眯。  基本语法 ``` syntax = “proto3”; package model; service MyServ { rpc Query(Reques returns(Reply); } message Student { int64 id = 1; string name = 2; int32 age = 3; } ``` 定义完 proto文件后,生成相应语言的代码 ``` protoc --proto_path=. --go_out=plugins=grpc,paths=source_relative:. xxxx.proto ``` `--proto_path` 或者 `-I` 参数用以指定所编译源码(包括直接编译的和被导入的 proto 文件)的搜索路径 `--go_out` 参数之间用逗号隔开,最后用冒号来指定代码目录架构的生成位置 ,`--go_out=plugins=grpc`参数来生成gRPC相关代码,如果不加`plugins=grpc`,就只生成`message`数据 eg:--go_out=plugins=grpc,paths=import:. 。注意一下 paths 参数,他有两个选项,import 和 source_relative 。默认为 import ,代表按照生成的 go 代码的包的全路径去创建目录层级,source_relative 代表按照 proto 源文件的目录层级去创建 go 代码的目录层级,如果目录已存在则不用创建 `protoc`是通过插件机制实现对不同语言的支持。比如 `--xxx_out` 参数,那么protoc将首先查询是否有内置的xxx插件,如果没有内置的xxx插件那么将继续查询当前系统中是否存在protoc-gen-xxx命名的可执行程序。 例如,生成 c++代码 ``` protoc -I . --grpc_ou
https://img2020.cnblogs.com/blog/342595/202012/342595-20201230132157802-1560391435.png) `protobuf`目前支持这5种数据类型,还有2个是已经废弃了。`protobuf`是语言无关的,也就是说,无论具体的语言支持哪些数据类型,在`marshal`的时候都要转换成这几种,在`unmarshal`的时候再转换成具体语言的类型 我们把一个结构转换成json ``` Student { Id: 1, Name: "孙悟空", Age: 300, } ``` ``` { "id": 1, "name": "孙悟空", "age": 300 } ``` 转换成 `protobuf` 数据格式 ``` 1000 1 10010 1001 11100101 10101101 10011001 11100110 10000010 10011111 11100111 10101001 10111010 11000 10101100 10 ``` 转换成十进制 ``` 8 1 8 9 229 173 153 230 130 159 231 169 186 24 172 2 ``` `json`一眼就能看懂是什么 ,`protobuf`数据格式看不明白,下面来解释这些数据都是什么。 ### index 和类型 先说一下第一个byte `1000` 这个表示的是字段的`index`和类型, `protobuf` 把一个字段的 index 和类型放在了一起 ``` (field_number << 3) | wire_type ``` 最后3个bit为类型,前面的bit为index `0000 1000` 首位为标识位,index为 1 后三位为wire_type:0(Varint类型)再比如 `10010` index: 2 wire_type: 2(Length-delimited类型) ### Varint类型 `Varint`数据类型,最高位(msb)标志位,为1说明后面还有byte,0说明后面没有byte,使用后面的7个Bit位存储数值 `Id: 1` protobuf对应的数据是`0000 0001` 这个很好理解 `Age: 300` protobuf对应的数据是`1010 110。
