介绍和上一篇。我们已经对Google的protobuf有了基本的了解,可以使用相应的工具生成相应的代码。但是对于.proto文件的格式和具体支持的类型不是很清楚。今天这篇文章就带你一探究竟。注意本文描述的协议是proto3版本。定义消息protobuf中的body称为message,可以看成是我们在程序中定义的类。我们可以在.proto文件中定义这个消息对象,并为其添加属性,如下:syntax="proto3";消息SearchRequest{字符串查询=1;int32page_number=2;int32result_per_page=3;}上面的例子第一行指定了.proto文件的协议类型。这里使用的是proto3,也是最新版本的协议。如果未指定,则默认为proto2。类型定义这里我们为SearchRequest对象定义了三个属性,类型分别为String和int32。String和int32都是简单类型。protobuf支持的简单类型如下:protobuf类型描述对应java类型double双精度浮点型doublefloat浮点型floatint32整数,最好不是负数intint64整数,最好不是表示负数longuint32无符号整数intuint64unsignedintegerlongsint32有符号整数intsint64有符号整数longfixed32四字节整数intfixed648字节整数longsfixed324字节有符号整数intsfixed648字节有符号整数longboolbooleanbooleanstringstringStringbytesbyteByteString当然protobuf也支持复杂的组合类型和枚举类型。枚举类型在protobuf中用enum表示。我们来看一个枚举类型的定义:messageSearchRequest{stringquery=1;int32page_number=2;int32result_per_page=3;枚举语料库{UNIVERSAL=0;网络=1;图像=2;本地=3;新闻=4;产品=5;视频=6;}Corpuscorpus=4;}上面我们定义了一个枚举类型Corpus,枚举类型中定义的枚举值都是从0开始的,0也是枚举类型的默认值。在枚举中,也可以定义一个具有相同值的枚举类型,但需要添加optionallow_alias=true,如下所示:未知=0;开始=1;运行=1;}}消息MyMessage2{枚举EnumNotAllowingAlias{未知=0;开始=1;//运行=1;//取消注释此行将导致Google内部出现编译错误并在外部出现警告消息。}}在枚举类型中,如果我们后面删除了一些枚举类型,删除的值可能会被后续用户使用,从而造成潜在的代码隐患。为了解决这个问题,枚举提供了一个保留关键字Word,这个关键字声明的枚举类型后面不会再用到,如下所示:enumFoo{reserved2,15,9to11,40tomax;reserved"FOO","BAR";}reserved关键字也可以用在message字段中,表示以后不要再使用这些字段,如下:messageFoo{reserved2,15,9to11;reserved"foo","bar";}我们可以看到字段的值,每个消息字段都被赋值,每个字段的值在消息中是唯一的,这些值用来定位字段位置在二进制消息格式中。所以一旦定义,不要随意修改。需要注意的是,值1-15在二进制中用1个字节表示,而值16-2047需要用2个字节表示,所以1-15通常用在最常见的字段和可能重复的字段中,这编码后节省空间。最小值为1,最大值为2的1的29次方,即536,870,911。19000-19999为预留号码,不可使用。消息被编译后,每个字段都会被转换成对应的类型,每个字段类型会被赋予不同的初始值。strings默认值为空字符串,bytes默认值为空字节,bools默认值为false,数值类型默认值为0,枚举类型默认值为枚举第一个元素.字段描述符每个消息字段可以有两个描述符。第一个称为单数,这意味着消息中可以有0或1个字段。这是proto3中默认的定义方式。第二种叫repeated,意思是这个字段在消息中可以重复出现,也就是说代表一个集合。添加注释proto中的注释类似于C++的样式,可以使用://或/.../的样式进行注释,如下所示:/*Thisisacomment。*/messageSearchRequest{字符串查询=1;int32page_number=2;//页数int32result_per_page=3;//每个页面的结果}嵌套类型消息也可以嵌入消息中,如下所示:messageSearchResponse{messageResult{stringurl=1;字符串标题=2;重复的字符串片段=3;}repeatedResultresults=1;}在上面的例子中,我们在SearchResponse中定义了一个Result类型。在java中,其实可以看做是一个嵌套类。如果想在message的定义类之外使用这个内部消息,可以通过_Parent_._Type_来定义:messageSomeOtherMessage{SearchResponse.Resultresult=1;}嵌套类型可以任意嵌套,如下所示:messageOuter{//Level0messageMiddleAA{//Level1messageInner{//Level2int64ival=1;布尔布尔=2;}}messageMiddleBB{//Level1messageInner{//Level2int32ival=1;布尔布尔=2;}}}Map如果要在proto中定义map,可以这样写:map
