protobuf 3 定义的犄角旮旯
Posted 香菜聊游戏
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了protobuf 3 定义的犄角旮旯相关的知识,希望对你有一定的参考价值。
最近在制定一些协议,虽然用了也很久了,但是还是会有一些迷惑,不确定的东西,整理下,备用。
1、数据类型对应关系
.proto类型 | Notes | C++ Type | Java/Kotlin | Python |
double | double | double | float | |
float | float | float | float | |
int32 | 使用可变长度编码。对负数进行编码效率低下——如果您的字段可能有负值,请改用 sint32。 | int32 | int | int |
int64 | 使用可变长度编码。对负数进行编码效率低下——如果您的字段可能有负值,请改用 sint64。 | int64 | long | int/long [4] |
uint32 | 使用可变长度编码。 | uint32 | int | int/long [4] |
uint64 | 使用可变长度编码。 | uint64 | long | int/long [4] |
sint32 | 使用可变长度编码。带符号的 int 值。这些比常规 int32 更有效地编码负数。 | int32 | int | int |
sint64 | 使用可变长度编码。带符号的 int 值。这些比常规 int64 更有效地编码负数。 | int64 | long | int/long |
fixed32 | 总是四个字节。如果值通常大于 228,则比 uint32 更有效 . | uint32 | int | int/long |
fixed64 | 总是八个字节。如果值通常大于 256,则比 uint64 更有效。 . | uint64 | long | int/long |
sfixed32 | 总是四个字节。 | int32 | int | int |
sfixed64 | 总是八个字节。 | int64 | long | int/long [4] |
bool | bool | boolean | bool | |
string | 字符串必须始终包含 UTF-8 编码或 7 位 ASCII 文本,并且不能超过 232。 . | string | String | str/unicode |
bytes | 可能包含不超过 2 32的任意字节序列。 . | string | ByteString | str (Python 2) bytes (Python 3) |
2、字段默认值
类型 | 默认值 |
string | “” |
bytes | |
numeric | 0 |
enum | 第一个枚举,并且枚举值为0 |
列表 | null |
3、枚举类型
3.1 枚举正常定义
enum Corpus
CORPUS_UNSPECIFIED = 0;
CORPUS_UNIVERSAL = 1;
CORPUS_WEB = 2;
CORPUS_IMAGES = 3;
CORPUS_LOCAL = 4;
CORPUS_NEWS = 5;
CORPUS_PRODUCTS = 6;
CORPUS_VIDEO = 7;
message SearchRequest
string query = 1;
int32 page_number = 2;
int32 result_per_page = 3;
Corpus corpus = 4;
第一个枚举的值必须为0,因为0 是默认值,0 必须是第一个,保持和proto2 兼容
3.2 别名
您可以通过将相同的值分配给不同的枚举常量来定义别名。为此,您需要将allow_alias选项设置为true,否则协议编译器将在找到别名时生成错误消息。
enum EnumAllowingAlias
option allow_alias = true;
EAA_UNSPECIFIED = 0;
EAA_STARTED = 1;
EAA_RUNNING = 1;
EAA_FINISHED = 2;
3.3 删除枚举兼容旧数据
如果你在版本开发的过程中移除了某个枚举,但是在老的协议中还会使用,可以使用reserved 关键字标识
enum Foo
reserved 2, 15, 9 to 11, 40 to max;
reserved "FOO", "BAR";
注意:不要使用负数作为枚举值,编码效率低。
4、map类型
在开发的过程中经常需要使用关联字段,很自然的想到使用map,protobuf也提供了map的类型,不知道你用过没有,反正我没用过
message VehPeriodData
string vehicleId = 1; // 车辆id
map<string,string> mapdata = 2;
注意:
- map 字段前面不能是repeated
- 数据的顺序不可靠
5、oneof
如果您有一条包含多个字段的消息,并且最多同时设置一个字段,可以强制执行此行为并使用 oneof 功能节省内存。
oneof 字段与常规字段一样,除了一个 oneof 共享内存中的所有字段外,最多可以同时设置一个字段。设置 oneof 的任何成员会自动清除所有其他成员。
message SampleMessage
oneof test_oneof
string name = 4;
SubMessage sub_message = 9;
注意:
- oneof 字段不能使用repeated
- 只会保留最后一个设置的字段值
6、选项
文件中的各个声明.proto可以用许多 选项进行注释。选项不会改变声明的整体含义,但可能会影响它在特定上下文中的处理方式。可用选项的完整列表在 中定义
google/protobuf/descriptor.proto。
6.1 java_package(文件选项)
要用于生成的 Java/Kotlin 类的包。如果文件中没有给出明确java_package的选项,默认情况下将使用 proto 包(使用文件中的“package”关键字指定.proto)。
option java_package = "com.example.foo";
6.2 java_outer_classname(文件选项)
生成的包装 Java 类的类名(以及文件名)。如果文件中没有明确 java_outer_classname指定,.proto则将通过将.proto文件名转换为驼峰式来构造类名(因此 foo_bar.proto变为FooBar.java)。如果该java_multiple_files选项被禁用,那么所有其他类/枚举/等。为文件生成的.proto 文件将在这个外部包装 Java 类中生成为嵌套类/枚举/等。如果不生成 Java 代码,则此选项无效。
option java_outer_classname = "Ponycopter";
6.3 java_multiple_files(文件选项)
如果为 false,则只会.java为此文件生成一个.proto文件,以及所有 Java 类/枚举/等。为顶级消息、服务和枚举生成的将嵌套在外部类中。如果为 true,.java将为每个 Java 类/枚举/等生成单独的文件。为顶级消息、服务和枚举生成,并且为此.proto文件生成的包装 Java 类将不包含任何嵌套类/枚举/等。 如果不生成 Java 代码,则此选项无效。
option java_multiple_files = true;
6.4 deprecated(字段选项)
如果设置为true,则表示该字段已弃用,不应被新代码使用。在大多数语言中,这没有实际效果。在 Java 中,这成为@Deprecated注解。
int32 old_field = 6 [deprecated = true];
以上是关于protobuf 3 定义的犄角旮旯的主要内容,如果未能解决你的问题,请参考以下文章
virtualbox报错:无法分配USB设备xxxx到虚拟电脑
virtualbox报错:无法分配USB设备xxxx到虚拟电脑