w酒店,婴儿体温-在线购物品牌,网络购物省钱小妙招

Pro镇妖册to3入门

本文根据Google供给的ProtolBuffer LanguageGuide英文文档: ProtolBuffer3 Language Guide

Proto北京太平间守夜员急招Buf的API文档

界说一个message

首先以一个简略的比方最初:比方查百度,那么需求一个查询句子:query,还有查询的页面号:page_number,然后便是查询的每一页的结丈夫要出墙果数:result_per_page。 这样就有三个字段:querypage_numberresult_per_page。 那么这个音讯(message)界说如下:

/*选中语法格局proto3w酒店,婴儿体温-在线购物品牌,网络购物省钱小好办法,也便是ProtocolBuffer的版别3*/
syntax = "proto3";
/*界说一个音讯,音讯姓名为SearchReqw酒店,婴儿体温-在线购物品牌,网络购物省钱小好办法uest*/
message SearchRequest{
/*键值对,每个字段则需求字段名和详细的类型*/
string query = 1;
int32 page_number = 2;
int32 result_per_page = 3;
}
仿制代码

关于每一个字段,有必要指定详细的类型

除了一个根底类型(字符串string,整型int32等)还能够界说其他归纳类型,如枚举类型和其他的message类型。后边将列出。

分配字段号

在上面界说的SearchRequest音讯中,关于每个字段,都有仅有标识的编号。这些字段号在音讯(message)的二进制格局中仅有辨认,在该音讯(message)投入到运用后不该该被更改。 在ProtocolBuffer中将音讯序列化为二进制后,关于1~15编号的字段,只需求一个字节编码,关于16~2047则需求两个字节。所以,关于把常常运用的字段元素编号到1~15中,而且预留(reserved)几位以便于今后扩展。 字段号的规模为:1~536870911(2^29-1)。其间19000~19999为ProtocolBuffer自己预留(reserved)的字段号不能运用。其他都能够自己运用。当然,自己预留(reserved)的编号在后续扩展也不能运用。关于预留(reserved)的后边将讲到。

指定字段规矩

音讯(message)的字段能够运用两种规矩描绘(proto2与proto3不同):

  • 单一的(singular):0个或1个,不必在字段界说中指出。
  • 重复的(repeated):0个到多个,需求在字段界说中指出。 看如下比方:一个人,只要一个正式的姓名(在刚出生的时分姓名还没挂号),可是他能够有多个外号,也能够没有。
 syntax = "proto3";
message Person{
string name = 1;
repeated string nickname = 2;
}
仿制代码

增加更多的音讯类型

多个音讯类型能够在一个.proto文件中界说。 比方在上面SearchRequest中增加一个SearchResponse。

message SearchRequest{
string query = 1;
int32 page_number = 2;
int32 result_per_page = 3;
}
message SearchResponse{
repeated string result = 1;
int32 page_number = 2;
}
仿制代码

注释

在.proto文件中注释为C/C++风格,用//注释单独,或/**/注释多行。

预留(reserved)字段

前面说到ProtocolBuffer自己预留(reserved)的字段号19000~19999。 能够自己预留字段名或许字段杨子珊号,这样预留(reserved)的字段将不会被今后的用户修改了。

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

编译器编译.proto文件娄底

能够运用ProtocolBufer编译器将.proto文件编译成自己挑选的言语。在之后能够运用编译后的音讯(message)进行get/set字段值,序列化音讯(message)到输出流,或许从输入流中反序列化得到音讯(message)。

  • C++:一个.proto文件编译生成一对.h和.cc文件。
  • Java:生成.java文件,运用音讯(message)指定的Builder类创立音讯(message)目标的实例。
  • Python:Python有点不相同:会生成一个module其间包括每个音讯(message)的静态描绘符。
  • Go:每一个音讯(message)生成一个.pb.go文件。
  • Ruby:生成.rb文件,是一个module中包括各个音讯(message)。
  • Objective-C:一个.proto文件生成一对pbobjc和pbobjc.m文件,每个音讯(message)对应一个class。
  • C#:生成.cs文件,每个音讯(message)对应一个class。
  • Dart:生成.pb.d仙侠小说art文件,每个音讯(message)对应一个class。

根底类型

  • double
  • float
  • int32:运用可变长编码,假如运用的该字段会有负数,功率将变低,这时最好运用sint32。
  • int64:运用可变长编码,假如运用的该字段会有负数,功率将变低,这时最好运用sint64。
  • uint32:运用可变长编码。
  • uint64:运用可变长编码。
  • sin32:运用可变长编码,有符号整形,有负数时运用惯例的int32更有功率。
  • sint64:运用可变长编码,有符号整形,有负数时运用惯例的int64更有功率。
  • fixed32:固定4个字节,假如数字大于2^28比uint32更有功率。
  • fixed64:固定8个字节,假如数字大于2^56比uint64更有功率。
  • sfixed32:固定4个字节。
  • sfixed64:固定8个字节。
  • bool
  • string:字符串,有必要运用UTF-8或许7位ASCII编码格局。
  • bytes:有恣意的byte序列。 详细的proto中各个字段类型映射到对应言语中时,见下图:


默许值

假如一个音讯(message)被解析了,可是其间的字段并没有被赋值,那么将会被设置为默许值。

  • string:空串
  • bytes:空的bytes序列
  • bool:false
  • 数字类型:0
  • 枚举类型:默许值为枚举类型中界说的第一个值,也便是0
  • 音讯类型(message:取决于所编译的言语。 关于repeated,为空的list。

枚举

这儿还w酒店,婴儿体温-在线购物品牌,网络购物省钱小好办法是以之前的查百度的比方来说,有了查询关键字query,关于成果,你有或许不只是想要阅读一下WEB页面,还行看看视频、图片、新闻啥的。那么这样界说:

syntax = "proto3";
message SearchRequest{
string query = 1;
int32 page_number = 2;
int32 result_per_page = 3;
enum Category{
option allow_alias = true;
//第一个值有必要为0。
UNIVERSAL =丢失的方舟 0;
WEB = 1;
IMAGES = 2;
NEWS = 3;
PRODUCT = 4;
VIDEO = 5;
//启用了别号,则能够赋同一个值
GENERAL = 0;
}
Category result_type = 4;
}
仿制代码

运用enum关键字界说枚举类型。 枚举常量数值有必要在32bit的整型中。运用负数赋值枚举常量功率低,不引荐。关于枚举常量,能够界说在音讯(message)中,也可界说在音讯(message)外。比方上面界说在Se查腾族archRequest中的Category,以SearchRequest.Category的办法来复用。

预留(reserved)值

相同的,关于音讯(message)中能够预留(reserved)字段号,在枚举中,能够预留(reserved)值。 下面预留(reserved)了,值,姓名。(2,15,9到11,40到最大值都不能后续运用)。

enum Foo {
reserved 2, 15, 9 to 11, 40 to max;
reserved "FOO", "BAR";
}
仿制代码

运用其他音讯(message)作为字段

之前界说的SearchRespon音讯(message):

message SearchResponse{
repeated string result = 1;
int32 page_number = 2;
}
仿制代码

关于成果,咱们只能获取多个字符串,让他回应的音讯功用更强大一点,咱们界说一个Result音讯(message):

message SearchResponse{
repeated Result result = 1;
int32 page_number = 2;
}
message Result{
string urlw酒店,婴儿体温-在线购物品牌,网络购物省钱小好办法 = 1;
string title = 2;
repeated string snippets = 3;
}
仿制代w酒店,婴儿体温-在线购物品牌,网络购物省钱小好办法码

在SearchRespon中,咱们嵌套了一个Result音讯(message),Result中有恳求的地址url,标题title还有描绘片段snippets。

嵌套界说

接下来,咱们再详细化URL:

message SearchResponse{
repeated Result result = 1;
int32 page_number = 2;
}
message Result{
URL url = 1;
string title = 2;
repeated string 琅琊榜小说snippets = 3;
}
message URL{
enum Protocol{
HTTP = 0;
HTTPS = 1;
}
Protocol protocol = 1;
string domainw酒店,婴儿体温-在线购物品牌,网络购物省钱小好办法 = 2;
int32 port = 3;
string filepath = 4;
}
仿制代码

关于SearchResponse音讯(message)中回来的成果result,在Result中又有音讯(message)URL,在URL中咱们详细到,运用的协议、域名、端口、恳求文件途径。所以,音讯之间能够相互嵌套,界说愈加杂乱的音讯。

导入

在Java中,或许其他言语,需求导入其他以及写好的包,在ProtocolBuffer中也是相同,能够导入从前界说好的.proto文件,运用其间界说的音讯(message)或许服务(service)。 在同一目录下,我将写好的URL放入URL.proto文件中,在界说SearchResponse音讯(message)中导入该文件:

import "URL.proto";
message Result{
URL url = 1;
string title = 2;
repeated string snippets = 3;
}
仿制代码

这样就能够复用更多的自界说音讯(message)了。 关于import,只能导入其后续指定的.proto文件中界说的音讯(message)或服务。比方有3个.proto文件:

/*file A.proto*/
syntax = "proto3";
message A{
}
/*file B.proto*/
syntax = "proto3";
import "A.proto";
message B{
A a = 1;
}
/*file C.proto*/
syntax = "proto3";
import "B.proto";
message C{
A a = 1;
}
仿制代码

在这其间,C是看不到A的,只要在B中import public "A.proto",C才干看见A。

Any字段类型

An崔熙瑞y字段类型是Google自己关于Proto中类型的封装,并供给必定特定办法。 如下界说一个Any字段,需求导入Google供给的any.proto

在Java中运用ErrorStatus音讯调用details的get办法时,回来的实例是com.google.protobuf.Any,关于该类型供给了pack和unpack办法,如下:class Any {
// 关于给定的音讯打包成Any类型,前缀则是默许的:type.googleapis.com
public ssm文tatic Any pack(Message message);
// 关于给定的音讯打包成Any类型,前缀则是typeUrlPrefix指定的
public static Any pack(Message message,
String typeUrlPrefix);
// 检查该Any类型是否是给定clazz的音讯类型
public boolean is(class clazz);
// 给定clazz音讯类型,将Any类型拆包成指定的音讯类型,假如不匹配抛出反常
public T unpack(class clazz)
throws InvalidProtocolBufferException;
}
仿制代码

Any字段给了必定的灵活性,在传递音讯时不必指定特定的类型,能够在传递不同音讯中传递不同的类型,在接纳端进行判别即可。在传输时,底层仍是被转换为bytes类型。

Oneof字段类型

Oneof类型如下界说。

oneof oneof_name {
int32 foo_int = 4;
string foo_string = 9;
...
}
仿制代码

关于这个oneof音讯类型,咱们能够这样了解,它相似与C言语中的union类型(联合体),最终生成的Java代码是这样的:

public enum OneofNameCase
implements com.google.protobuf.Internal.EnumLite {
FOO_INT(4),
FOO_STRING(排卵日9),
...
ONEOFNAME_NOT_SET(0);
...
};
仿制代码

假如设置了oneof_name音讯中的foo_int字段,那foo_string就无效。相同的,假如设置了foo_string字段,那么foo_int字段就无效。卧底在Oneof类型的音讯中,只要一片同享内存,每次只要一个字段被设置。 需求留意,Oneof的音讯不能运用repeated描绘。 在Java中供给了一下办法进行辅佐运用: 关于生成类中的枚举类:

  • int getNumber(): 回来在.proto文件中界说的索引值,如foo_int则回来4。
  • static OneofNameCase forNumber(int value): 回来运用索引值相应的目标,假如该目标未设置则回来null,如4则回来foo_int。 生成类中:
  • OneofNameCase getOneofNameCase(): 回来现已设置了的目标,假如都没有被设置回来ONEOFNAME_NOT_SET。 生成类中的Builder:
  • Builder clearOneofName(): 清空一切设置。

Map字段类型

运用这样界说Map类型:

map map_field = N;
仿制代码
  • key_type:能够运用任何惯例类型(int32或许string等),不能运用浮点数bytes类型界说。
  • value_type:能够是任何类型,除了又是一个Map。 和Oneof相同,运用Map界说的字段不能够是**repeated**的。

包:package

关于.proto文件,能够运用包安排,package字段便是相似于Java中的Package。 界说的核算CalculateMsg音讯,在proto.Calculation文件夹下:

其间的包便是Calculation。

最好运用package和文件夹想对应,在Java中的习气哈。界说服务Service

在这儿我运用上面CalculationMsg的音讯类,界说了其相应了服务,RPC(Remote Procedure Call)。 package Calculation;

import "Calculation/CalculatMsg.proto";
service Calculator{
rpc Calc( CalRequest ) returns (CalResponse){}
}
仿制代码

运用Proto编译器编译上面的文件,相应于挑选的言语将生成服务的接口(interface)和客户端的stub。 能够运用Google供给的gRPC,也能够运用第三方的RPC结构。 这儿我给我们看看仿照grpc.io供给比方写的核算服务: 关于服务端:

复写编译生成的gRPC接口类,完成之前界说的calc函数:获取恳求的需求核算办法,数值1和数值2,核算,然后放入输出流中,最终OnComplete。

客户端则先Build一个恳求,堵塞调用获取成果。映射到JSON

Proto3能够转换到JSON数据格局,其相应的数据类型映射如下: 假如Proto中某个字段未设置,在JSON中便是null。

选项O毛笔字帖ption

.proto文件中能够运用option字段声明特定选项。Opion不会影响全体音讯的界说,可是在特定的上下文中进行影响。 Option选项也是分级其他,有时分在外界说脐带血有必要保存吗,则影响的是文件等级,如:java_package、java_multiple_files、java_outer_classname等,分别是:编译后在哪个java包下,是否将.proto文件中不同音讯分红多个文件,界说编译后的java类名。

之前界说的核算服务便是如上,生成的package在tech.sylardaemon.Calculation中,生成后的类名Calcula即torProt,java_generic_services为true则是生成gRPC相应的服务接口和客户stsomeub。 还能够自己界说option,是ProtoBuf的一种高档运用,这儿就略过了,有爱好的同学能够自己查检查。编译器运用

编译器的运用如下:

protoc --pr一英镑等于多少人民币oto_path = IMPORT_PATH --Language_out = DST_DIR path/to/*.proto
仿制代码
  • --proto_path:该参数输入的IMPORT_PATH是指定你要编译的***.proto文件中import指令中查找的目录。假如省掉,则运用当时编译器履行的目录。也能够屡次运用--proto_path指定多个导入目录。能够运用-I**缩短。
  • --Language_out:能够供给一个或多个w酒店,婴儿体温-在线购物品牌,网络购物省钱小好办法输出目录:
  • --cpp_out:生成C ++代码的意图目录
  • --java_out:生成Java代码的意图目录
  • --python_out:生成Python代码的意图目录
  • --go_out:生成Go代码的意图目录
  • --ruby_out:生成Ruby代码的意图目录
  • --objc_out:生成Objective-C代码的意图目录
  • --csharp_out:生成C#代码的意图目录
  • --php_out:生成PHP代码的意图目录
  • path/to/*.proto:最终的则是将要被编译杏的proto文件途径。

作者:LudwigWuuu

链接:https://juejin.im/post/5c0a82ed6fb9a049ad76dd56

来历:掘金

著作权归作者一切。商业转载请联络作者取得授权,非商业转载请注明出处。

 关键词: