Protocol Buffers基础学习

一、概述:

        Protocol Buffers(简称protobuf):是谷歌定义的一种轻便高效的结构化数据存储格式,可用于结构化数据串行化,很适合做数据存储或RPC数据交换格式。它可用于通讯协议、数据存储等领域,与语言、平台无关、是可扩展的序列化结构数据格式。和XML干的事一样,但是比XML性能好。

二、安装:

        由于每种语言需要安装的插件都不同,所以就不再赘述,安装请自行百度。

三、使用:

        首先需要编写.proto文件的内容,然后对该文件进行编译就会生成对应语言的Bean类,该Bean类会继承ProtobufMessage类,它是在protobuf.so中自动加载的。最后创建Bean类的对象,然后就可以使用其类库的方法。

四、.proto文件格式:

        1、.proto文件内容组成:

       .proto文件基本组成部分是message,一个.proto文件可以包含多个message。message之间可以互相引用,message还可以嵌套message和枚举类。一个message通常包含至少一个字段,每个字段都包括:字段描述符、字段类型、字段名称和字段对应的Tag:

              1>字段描述符:可写可不写,有四个值可选:

                      ①singular:表示有0个或1个该字段的值。如果没有声明字段描述符,默认为singula。

                      ②repeated:表示可以有0个或多个该字段的值;

                      ③optional:表示该字段可选,不是必需字段。如果该字段未设置,会使用[default = xx]定义的默认值,如果default未定义默认值,会使用字段类型的默认值。

                      ④required:表示该字段必需。

              2>字段类型:可分成四类:

                      ①基本类型:double、float、bool、string、bytes、int32、int64、uint32、uint64、sint32、sint64、fixed32、fixed64、sfixed32、sfixed64;

                      ②Map类型:字段描述符不能是repeated,key的类型只能是整数型(包括各种int32和int64)和string类型,Map类型的数据是无序的;

                      ③message类型:可以引用其他message;

                      ④枚举类型:在protobuf中有个约束:枚举的第一项对应的值必须为0;

              3>字段对应的Tag:主要用于说明对应字段在二进制文件的对应关系,一旦指定,不应该在后续进行变更。Tag必须是数字且唯一,最大支持到536870911,中间有一段(19000~19999)是protobuf内部使用的。标记的值小于15时序列化编码为一个字节,大于15会用到两个及以上的字节。可以通过reserved关键字来预留Tag和字段名,还有一种场景是如果某个字段已经被废弃了不希望后续被采用,也可以用reserved关键字声明;

              oneof关键字:用于声明一组字段中,必须要有一个字段被赋值。当对oneof其中一个字段赋值时,oneof中其他字段的值将会被清空,所以只有最后一次赋值是有效的。

        2、protobuf设置:

              1>可以通过import关键字导入其他.proto文件,从而复用message类型;

              2>版本差异:protobuf现在主流的有2.X和3.X版本,两者之间相差比较大,默认为2.X版本,如果需要使用3.X版本,需要在文件开头声明:

syntax = "proto3";

              2.X版本是支持在字段中声明默认值的,但是在3.X版本中去掉了默认值的定义,主要是为了避免用户是否设置了一个和默认值一样的值的情况。对于3.X版本,protobuf采用以下规则处理默认值:

              对应string类型,默认值为一个空字符串;

              对于bytes类型,默认值为一个空的byte数组;

              对于bool类型,默认值为false;

              对于数值类型,默认值为0;

              对于枚举类型,默认值为第一项,也即值为0的那个枚举值;

              对于引用其他message类型:其默认值和对应的语言是相关的;

        3、protobuf扩展:protobuf具有很好的扩展性,但是要遵循以下原则:

              1>不能修改原有字段的Tag;

              2>如果新增一个字段,对于老的二进制序列化文件处理时会给这个字段增加默认值;如果是升级了proto文件而没有升级对应的代码,则新的字段会被忽略;

              3>可以删除字段,但是对应的Tag不应该再被使用,否则对于之前的二进制序列化消息处理时对应关系出现问题;

              4>int32、uint32、int64、uint64和bool类型是相互兼容的,可以在它们之间修改类型而不会有兼容性问题;

        4、示例:

syntax = "proto3";  //声明为protobuf 3
package xinxi;
import "google/protobuf/any.proto";  //导入protobuf自带的message

message Student {
    int32 id = 1;
    string name = 2;
    optional int32 age = 3 [default = 20];

    //性别为枚举类型
    enum SexType {
        MALE = 0;
        FEMALE = 1;
    }
    SexType sex = 4;

    int32 grade = 5;
    int32 class = 6;

    //多个兴趣使用repeated
    repeated string hobby = 7;
    
    //所学专业使用oneof关键字,文科理科工科只能三选一
    oneof professional{
        string wen = 1;
        string li = 2;
        string gong = 3;
    }

    //老师信息使用Map
    map<string, Teacher> teacher = 9;
}

message Teacher {
    int32 id = 1;
    string name = 2;
    int32 age = 3;
    int32 sex = 4;
}
发布了108 篇原创文章 · 获赞 31 · 访问量 16万+

猜你喜欢

转载自blog.csdn.net/lzghxjt/article/details/89256440