protobuf 3 定义的犄角旮旯

Posted 香菜+

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了protobuf 3 定义的犄角旮旯相关的知识,希望对你有一定的参考价值。

https://developers.google.com/protocol-buffers/docs/proto3

最近在制定一些协议,虽然用了也很久了,但是还是会有一些迷惑,不确定的东西,整理下,备用。

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;

注意:

  1. map 字段前面不能是repeated
  2. 数据的顺序不可靠

5、oneof

如果您有一条包含多个字段的消息,并且最多同时设置一个字段,可以强制执行此行为并使用 oneof 功能节省内存。

oneof 字段与常规字段一样,除了一个 oneof 共享内存中的所有字段外,最多可以同时设置一个字段。设置 oneof 的任何成员会自动清除所有其他成员。

message SampleMessage 
  oneof test_oneof 
    string name = 4;
    SubMessage sub_message = 9;
  

注意:

  1. oneof 字段不能使用repeated
  2. 只会保留最后一个设置的字段值

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 定义的犄角旮旯的主要内容,如果未能解决你的问题,请参考以下文章

iOS 犄角旮旯的知识

C++编程中使用框架protobuf

virtualbox报错:无法分配USB设备xxxx到虚拟电脑

virtualbox报错:无法分配USB设备xxxx到虚拟电脑

virtualbox报错:无法分配USB设备xxxx到虚拟电脑

新房装修,家里WiFi怎么弄?