74 lines
3.2 KiB
Markdown
74 lines
3.2 KiB
Markdown
- [protobuf](#protobuf)
|
||
- [language guide(proto3)](#language-guideproto3)
|
||
- [定义message type](#定义message-type)
|
||
- [Assign Field Numbers](#assign-field-numbers)
|
||
- [重复使用filed number的后果](#重复使用filed-number的后果)
|
||
- [指定字段基数](#指定字段基数)
|
||
- [Singular](#singular)
|
||
- [repeated](#repeated)
|
||
- [map](#map)
|
||
|
||
|
||
# protobuf
|
||
## language guide(proto3)
|
||
### 定义message type
|
||
如下为一个定义search request message format的示例,
|
||
```proto
|
||
synatx="proto3"
|
||
|
||
message SearchRequest {
|
||
string query = 1;
|
||
int32 page_number = 2;
|
||
int32 results_per_page = 3;
|
||
}
|
||
```
|
||
上述示例含义如下:
|
||
- `synatx = "proto3"`:
|
||
- 代表当前protobuf的language版本为`proto3`
|
||
- 如果没有指定`syntax`,那么protocol buffer compiler默认会假设在使用`proto2`
|
||
- `Search Request`消息定义了3个fields,每个field都代表`希望包含在message中的一部分数据`
|
||
|
||
### Assign Field Numbers
|
||
可以为message中的每个field定义一个整数,范围为`[1,536,870,911]`,并有如下约束
|
||
- message中所有field的给定数字必须唯一
|
||
- field number `[19,000, 19,999]`是为`Protocol Buffer`实现保留的,如果使用这些数字,protocol buffer compiler将会报错
|
||
|
||
一旦消息类型被使用后,field number就不能被改变,field number代表message wire format中的field。
|
||
|
||
如果对field的field number进行了修改,代表删除旧的field并且新建一个相同类型的field。
|
||
|
||
filed number不应该被重用。
|
||
|
||
对于`频繁被设置`的fields,应该将其的field number设置为`[1,15]`。在wire format中,field number的值越小占用空间越小。
|
||
|
||
> 例如,`[1,15]`在编码时只占用1字节,而`[16, 2047]`则会占用2字节。
|
||
|
||
### 重复使用filed number的后果
|
||
如果重复使用field number,将会造成解码wire-format message的二义性。
|
||
|
||
> 对于protobuf wire format,其在编码和解码过程中,`fields的定义`必须一致。
|
||
|
||
field number被限制为`29bit`,故而field number的最大值为`536870911`。
|
||
|
||
### 指定字段基数
|
||
在protobuf协议中,field可以为如下的集中类型
|
||
#### Singular
|
||
在proto3中,有两种singular field:
|
||
- `optional`(推荐使用): 一个optional field可能有如下两种状态
|
||
- 如果optional field值被设置,那么其将会被序列化到`wire`中
|
||
- 如果optional field值未被设置,那么该field将会返回一个默认值,并且其不会被序列化到wire中
|
||
- `implict`(不推荐使用):一个隐式字段没有显式基数标签,并且行为如下:
|
||
- 如果field为一个message type,那么其行为和`optional`相同
|
||
- 如果field不是message,那么其有两种状态:
|
||
- 如果field被设置为非默认值(non-zero),其会被序列化到wire中
|
||
- 如果field被设置为zero value,那么其不会被序列化到wire中
|
||
|
||
> 相比于`implict`,更推荐使用`optional`,使用`optional`能更好与proto2相兼容
|
||
|
||
#### repeated
|
||
代表该field可以在消息中出现0次或多次,消息出现的顺序也将被维护
|
||
|
||
#### map
|
||
代表field为成对的键值对
|
||
|