Protocol Buffers学习(1):定义一个消息

首先让咱们来看一个很是简单的例子。 假设你想定义一个消息格式,用来表示搜索请求,其中每一个搜索请求都有三项:javascript

  • 一个查询字符串
  • 你感兴趣的特定结果页
  • 以及每一个页面的结果数

下边是用来定义消息类型的.proto文件java

syntax = "proto3";

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}复制代码
  • 第一行表示使用的protocol版本是3,若是你不写这一条,protobuf会认为你使用的是protobuf2,并且,这行必须是第一行,前边也不能有注释
  • SearchRequest这条消息定义了三个字段(名称/值对),每条消息都要包含这三个字段,每一个字段都有一个名称和一个类型

字段类型说明

在上面的例子中,全部字段都是基本类型:两个整数(page_number和result_per_page)和一个字符串(query)。这些字段也能够是复合类型,包括枚举和其余消息类型ui

字段标签

消息定义中的每一个字段都有惟一的编号标签,这些标记用于以消息二进制格式标识字段,消息开始使用以后就不能修改编码

注意spa

  • 值在1到15范围内的标签须要一个字节进行编码,包括标识号和字段类型
  • 在16到2047范围内的标签占用两个字节。

所以,你应该为很是频繁出现的消息元素保留标签1到15。记住要为可能在未来添加的频繁出现的元素留出一些空间。code

最小的标签是1,最大的标签是536870911,即2^29 - 1,而且19000 - 19999protobuf系统保留标签,不能使用这几个接口

字段规则说明

一共有两种类型ip

  • singular: 一个符合规则的消息应该具有零个或者一个该字段
  • repeated: 一个符合规则的消息能够有零个或者任意个该字段,而且保留重复的顺序,在proto3中,基本类型的重复字段默认压缩编码

添加更多消息类型

能够在单个.proto文件中添加多个消息类型,例如字符串

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

message SearchResponse {
 ...
}复制代码

添加注释

可使用//.proto文件添加注释。例如编译器

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.
}复制代码

保留字段(字段修改或者删除解决办法)

当消息类型更新或者删除时,这些被修改的字段的标签若是继续使用,会形成数据不正确的问题,这时须要把这些标签保留起来,防止跟旧版本的数据发生冲突。
(当使用JSON序列化时,字段名称也有可能存在这个问题),通俗来讲,就至关于已经上线了使用A接口的一个APP,这个时候服务端若是想修改A接口的数据格式,只能新增一个接口,而且确定不能使用A接口的地址

案例

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}复制代码

这就表示 2,15,9,10,11,"foo", "bar"都不能重复使用了

.proto文件会生成什么?

当编译.proto文件时,编译器将根据你选择的语言生成对应代码,你须要使用文件中描述的消息类型,包括获取和设置字段值,将消息序列化 输出流,以及解析来自输入流的消息

  • 对于PHP,编译器会为每一个消息生成一个类,用来描述该消息
  • 对于C ++,编译器从每一个.proto生成.h.cc文件,并为您的文件中描述的每一个消息类型指定一个类
  • 对于Java,编译器会为每一个消息类型生成一个带有类的.java文件,以及用于建立消息类实例的特殊Builder类
  • Python有点不一样, Python编译器生成一个模块,其中包含.proto中每一个消息类型的静态描述符,而后使用元类在运行时建立必要的Python数据访问类
  • 对于Go,编译器会为文件中的每种消息类型生成一个具备类型的.pb.go文件
  • 对于Ruby,编译器生成一个包含消息类型的包含Ruby模块的.rb文件
  • 对于JavaNano,编译器输出与Java相似,但没有Builder类
  • 对于Objective-C,编译器从每一个.proto生成一个pbobjc.hpbobjc.m文件,在文件中描述的每一个消息类型都有一个类
  • 对于C#,编译器从每一个.proto生成一个.cs文件,在文件中描述的每一个消息类型都有一个类
相关文章
相关标签/搜索