起源
-
学习rpc服务的时候,接触到的谷歌推出的号称独立世界,哪儿哪儿都可以运行的一种语言。
-
尝试翻译一下Proto3的官方文档,以便自己学习和寻找解决方案
-
书读百遍其义自见
原文地址
https://developers.google.com/protocol-buffers/docs/proto3#simple
Defining A Message Type(如何定义一个消息体?)
描述信息
咱们先看一个简单的案例,首先创建一个.proto文件、 定义一个SearchRequest消息体,定义3个基本信息字段(m名称随便写,不用care),
syntax = "proto3";
message SearchRequest {
string query = 1;
int32 page_number = 2;
int32 result_per_page = 3;
}
备注说明
- 声明用的语法格式syntax = “proto3”,如果不明确指定用3的语法,默认就是2的语法格式
- SearchRequest包含3个字段,每个字段都类型(string,int32等),以及名称(query,page_number等)
字段类型
之前的小案例中,介绍了两种标准类型,String和Int.但是可以指定一些更复杂的类型比如enum 枚举类型。
.proto Type | Notes | Java Type | Python |
---|---|---|---|
double | 无 | double | float |
float | 无 | float | float |
int32 | 无 | int | int |
int32 | 无 | long | int/long |
… | … | … | … |
bool | … | Boolean | bool |
string | … | String | str |
分配字段number
上诉的案例中,每一个字段定义唯一标识(unique number).这些number决定着字段的编码格式参考:https://developers.google.com/protocol-buffers/docs/encoding。 number 范围在1-15中 用采取对每一个字节编码,16-2047将会2个字节进行编码。
number最小为1 最大为 536,870,911。不要使用19000 到 19999,不要使用已经使用的number值。
定义字段规则
- 定义一个字段或者多个字段,相比2语法,少了required和optional定义字段
- repeated 可以立即为Java中的List
添加多个消息
一个.proto文件中,可以定义多个消息体
message SearchRequest {
string query = 1;
int32 page_number = 2;
int32 result_per_page = 3;
}
message SearchResponse {
...
}
添加注释
使用/* …代码块… */或者 //代码块
保留字段
预防担心以后的人瞎JB改东西或者定义不规范,自己写保留几个字段field或者number,注意千万不要重复
怎么生成自己的Proto文件
https://developers.google.com/protocol-buffers/docs/reference/overview参考官网自己去看想用的语言提供的Api,没别的招,请自学
枚举类型
很多时候,你会预先定义一些值。比如SearchRequest中的 Corpus字段,
message SearchRequest {
string query = 1;
int32 page_number = 2;
int32 result_per_page = 3;
enum Corpus {
UNIVERSAL = 0;
WEB = 1;
IMAGES = 2;
LOCAL = 3;
NEWS = 4;
PRODUCTS = 5;
VIDEO = 6;
}
Corpus corpus = 4;
}
正如案例重演示的一样,Corpus第一个字段标识number必须从0开始,number范围在0-32之间。如果定义的常量超过32个,建议使用2个枚举类型
…
使用其他消息类型
引用其他文件消息体
import "myproject/other_protos.proto";
引用其他文件并且使用
嵌套消息体
- 常规嵌套
message SearchResponse {
message Result {
string url = 1;
string title = 2;
repeated string snippets = 3;
}
repeated Result results = 1;
}
- 按您喜好嵌套无论多少层(个人建议3层即可)
message Outer { // Level 0
message MiddleAA { // Level 1
message Inner { // Level 2
int64 ival = 1;
bool booly = 2;
}
}
message MiddleBB { // Level 1
message Inner { // Level 2
int32 ival = 1;
bool booly = 2;
}
}
}
更新消息体注意事项
- 不要修改已存字段number
- 字段确认不用后再移除
- int32, uint32, int64, uint64这几种类型都是兼容的,
- 多个消息体的可以使用oneof关键字
Any
暂时没用过
Oneof
- 同时将多个字段定义在一个结构体内,并且能够节约内存存放数据
- oneof 不可以使用repeated
message StudentMessage {
enum dateType {
StudentType = 0;
TeacherType = 1;
}
dateType d_type = 1;
oneof body {
Student stuednt = 2;
Teacher teacher = 3;
}
}
message Student {
string name = 1;
int32 age = 2;
string address = 3;
}
message Teacher {
string name = 1;
}
- JAVA版本
StudentProtos.StudentMessage.Builder studentMessageBuilder = StudentProtos.StudentMessage.newBuilder();
studentMessageBuilder.setDType(StudentProtos.StudentMessage.dateType.StudentType);
StudentProtos.Student.Builder builder = StudentProtos.Student.newBuilder();
builder.setName("张三");
builder.setAddress("成都");
builder.setAge(10);
StudentProtos.Student student = builder.build();
studentMessageBuilder.setStuednt(student);
StudentProtos.StudentMessage message = studentMessageBuilder.build();
Options
浏览了下说明,主要是针对JAVA。
-
option java_package = “com.example.foo”; 定义生成文件目录
-
option java_outer_classname = “Ponycopter”; 定义JavaClass
-
其他暂时可以忽略