Protobuf使用

Protobuf使用

github地址

目录

proto3的更新

  • 在第一行非空白非注释行,必须写:
syntax  = "proto3";
  • 字段规则移除了 required,并把 optional 改名为 singular;
    proto2required 也是不推荐使用的。proto3 直接从语法层面上移除了 required规则。其实可以做的更彻底,把所有字段规则描述都撤销,原来的repeated 改为在类型或字段名后加一对中括号。这样是不是更简洁?

  • repeated字段默认采用 packed 编码;
    proto2 中,需要明确使用 [packed=true] 来为字段指定比较紧凑的 packed 编码方式。

  • 移除了default 选项;
    proto2 中,可以使用 default 选项为某一字段指定默认值。在 proto3 中,字段的默认值只能根据字段类型由系统决定。也就是说,默认值全部是约定好的,而不再提供指定默认值的语法。
    在字段被设置为默认值的时候,该字段不会被序列化。这样可以节省空间,提高效率。
    但这样就无法区分某字段是根本没赋值,还是赋值了默认值。这在 proto3 中问题不大,但在 proto2 中会有问题。
    比如,在更新协议的时候使用 default 选项为某个字段指定了一个与原来不同的默认值,旧代码获取到的该字段的值会与新代码不一样。

  • 枚举类型的第一个字段必须为 0 ;

  • 移除了对分组的支持;
    分组的功能完全可以用消息嵌套的方式来实现,并且更清晰。在 proto2 中已经把分组语法标注为『过期』了。这次也算清理垃圾了。

  • 移除了对扩展的支持,新增了 Any 类型;
    Any 类型是用来替代 proto2 中的扩展的。目前还在开发中。
    proto2 中的扩展特性很像 Swift 语言中的扩展。理解起来有点困难,使用起来更是会带来不少混乱。
    相比之下,proto3 中新增的 Any 类型有点像 C/C++ 中的 void* ,好理解,使用起来逻辑也更清晰。

  • 增加了 JSON 映射特性;
    语言的活力来自于与时俱进。当前,JSON 的流行有其充分的理由。很多『现代化』的语言都内置了对 JSON 的支持,比如 GoPHP 等。而 C++ 这种看似包罗万象的学院派语言,因循守旧、故步自封,以致于现出了式微的苗头。

  • map支持

map<key_type, value_type> map_field = N;
example:
map<string, Project> projects = 3;
  • 在 proto3 中,纯数字类型的 repeated 字段编码时候默认采用 packed 编码(具体原因见 Protocol Buffer 编码原理 这一章节)

定义协议格式

.proto文件中的定义很简单:为要序列化的每个数据结构添加消息,然后为消息中的每个字段指定名称和类型。这是.proto定义您的消息的文件addressbook.proto

(好的.proto文件命名风格是:packagename.messagename.proto)

syntax = "proto3";

package tutorial;

message Person {
  string name = 1;
  int32 id = 2;
  string email = 3;

  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

  message PhoneNumber {
    string number = 1;
    PhoneType type = 2;
  }

  repeated PhoneNumber phones = 4;
}

message AddressBook {
  repeated Person people = 1;
}

.proto文件以包声明开头,这有助于防止不同项目之间的命名冲突。在C++中,生成的类将放在与包名匹配的命名空间中。

每个元素上的“= 1”,“= 2”标记标识该字段在二进制编码中使用的唯一“标记”。标签号1-15需要少于一个字节来编码而不是更高的数字,因此作为优化,您可以决定将这些标签用于常用或重复的元素,将标签16和更高版本留给不太常用的可选元素。重复字段中的每个元素都需要重新编码标记号,因此重复字段特别适合此优化。

可以指定的最小字段编号为1,最大字段编号为229-1 或 536,870,911。也不能使用数字 19000 到 19999(FieldDescriptor :: kFirstReservedNumber 到 FieldDescriptor :: kLastReservedNumber),因为它们是为 Protocol Buffers实现保留的。

必须使用以下修饰符之一注释每个字段:

  • required(proto3中移除):必须提供该字段的值,否则该消息将被视为“未初始化”。如果libprotobuf在调试模式下编译,则序列化未初始化的消息将导致断言失败。在优化的构建中,将跳过检查并始终写入消息。但是,解析未初始化的消息将始终失败(通过false从解析方法返回)。除此之外,必填字段的行为与可选字段完全相同。

  • optional(proto3中为singular):该字段可能已设置,也可能未设置。如果未设置可选字段值,则使用默认值。对于简单类型,您可以指定自己的默认值,就像我们type在示例中为电话号码所做的那样。否则,使用系统默认值:数字类型为0,字符串为空字符串,boolsfalse。对于嵌入式消息,默认值始终是消息的“默认实例”或“原型”,其中没有设置其字段。调用访问器以获取尚未显式设置的可选(或必需)字段的值始终返回该字段的默认值。

  • repeated(proto3默认采用 packed 编码):该字段可以重复任意次数(包括零)。重复值的顺序将保留在协议缓冲区中。将重复字段视为动态大小的数组。

  • proto3 中移除了default选项:字段的默认值只能根据字段类型由系统决定。也就是说,默认值全部是约定好的,而不再提供指定默认值的语法。在字段被设置为默认值的时候,该字段不会被序列化。这样可以节省空间,提高效率。

编译protobuf

现在运行编译器,指定源目录(应用程序的源代码所在的位置 - 如果不提​​供值,则使用当前目录),目标目录(您希望生成的代码在哪里;通常相同$SRC_DIR) ,以及你的道路.proto。:

protoc -I = $ SRC_DIR --cpp_out = $ DST_DIR $ SRC_DIR / addressbook.proto

这里都生成到当前目录,输入

protoc -I=. --cpp_out=. .
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值