Language Guide (proto3) | proto3 语言指南(一)定义消息类型

定义消息类型

首先让我们看一个非常简单的例子。假设您想定义一个搜索请求消息格式,其中每个搜索请求都有一个查询字符串、您感兴趣的特定结果页以及每页的结果数。下面是用于定义.proto消息类型的文件。

syntax = "proto3";

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}
  • 文件第一行指定您使用的语法:如果不这样做,协议缓冲区编译器将假定您使用的是proto2。这必须是.proto3文件的第一个非空、非注释行。
  • 消息定义指定了三个字段(名称/值对),每个字段对应于要包含在该类型消息中的数据段。

指定字段类型

在上面的例子中,所有的字段都是标量类型:两个整数和一个字符串。但是,你同样可以为你的字段指定复合类型,包括枚举和其他消息类型。

分配字段编号

如您所见,消息定义中的每个字段都有一个唯一编号。这些字段编号用于标识消息二进制格式的字段,并且在消息类型投入使用后不应更改。请注意,1到15范围内的字段编号需要一个字节进行编码,编码内包括字段号和字段类型(您可以在协议缓冲区编码中了解更多信息)。16到2047范围内的字段编号需要两个字节(进行编码)。因此,您应该把1到15的消息编号留给非常频繁出现的消息元素。请记住为将来可能添加的频繁出现的元素留出一些空间。可以指定的最小字段号为1,最大字段号为229-1或536870911。您也不能使用数字19000到19999(字段描述符),因为它们是协议缓冲区的保留数字,如果你在你的.proto中使用了这些数字,编译器会报错。同样,不能使用任何以前保留的字段号。

指定字段规则

消息字段可以是以下字段之一:

  • singular(单一的):格式良好的消息可以有零个或一个字段(但不能超过一个),这是proto3语法的默认字段规则。
  • repeated(重复的):此字段可以在格式良好的消息中重复任意次数(包括零次),重复值的顺序将被保留。
    在proto3中,标量数字类型的重复字段默认使用压缩(packed)编码。
    您可以在协议缓冲区编码中找到有关压缩编码的更多信息。

添加更多消息类型

在一个.proto文件中可以定义多种消息类型。建议您在一个.proto文件中定义多个相关的消息类型。例如,如果要定义与SearchResponse消息类型对应的回复消息格式,可以将其添加到同一个.proto文件中:

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}

添加注释

.proto文件的注释和C/C++语法一样,//用作单行注释,/*...*/用作多行注释:

/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}

保留字段

如果通过完全删除某个字段或把它注释掉来更新消息类型,则将来的用户可以在对该类型进行自己的更新时重用该字段编号。如果以后加载相同.proto的旧版本,这可能会导致数据损坏、隐私漏洞等严重问题。确保不会发生这种情况的一种方法是使用reserved关键字指定已删除字段的字段编号为保留编号(也要指定已删除字段名称为保留名称(name),以规避JSON序列化问题)。将来有任何用户试图使用这些字段标识符时,协议缓冲区编译器将报错。

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}

不能在同一个reserved语句中混合使用字段名和字段号。

你的.proto文件生成了什么?

运行协议缓冲区编译器编译.proto文件时,编译器将以您选择的语言生成代码。您将需要使用文件中描述的消息类型,来进行获取和设置字段值、将消息序列化为输出流以及从输入流解析消息等工作。

  • 对于C++,编译器从每个.proto成一个.h.cc文件,其中每个文件中描述的每个消息类型都有一个类。
  • 对于Java,编译器生成一个.Java文件,其中包含每个消息类型的类,以及用于创建消息类实例的特殊生成器类。
  • Python有点不同–Python编译器生成一个模块,其中包含.proto中每个消息类型的静态描述符,然后与元类一起使用,在运行时创建必要的Python数据访问类。
  • 对于Go,编译器为文件中每种消息类型生成一个.pb.go文件。
  • 对于Ruby,编译器生成一个.rb文件,其中包一个Ruby模块,模块中包含你文件中的消息类型。
  • 对于Objective-C,编译器从每个.proto生成一个pbobjc.hpbobjc.m文件,并为文件中描述的每个消息类型生成一个类。
  • 对于C#,编译器从每个.proto生成一个.cs文件,其中每个消息类型对应一个类。
  • 对于Dart,编译器从每个.proto生成一个.pb.dart文件,其中每个消息类型对应一个类。
    通过遵循所选语言的教程(proto3版本即将推出),您可以了解更多关于为每种语言使用api的信息。有关更多API详细信息,请参阅相关API参考(proto3版本也即将推出)。

原文:https://www.cnblogs.com/itheo/p/14272852.html

作者:Theo·Chan
版权:本文版权归作者和博客园共有
转载:欢迎转载,但未经作者同意,必须保留此段声明;必须在文章中给出原文连接,否则必究法律责任
posted @ 2021-01-13 16:34  Theo·Chan  阅读(819)  评论(0编辑  收藏  举报