比 Json 还牛的 Protobuf 的编码须知(.proto文件该如何编写)(一)

293 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第5天,点击查看活动详情

编码规范:

定义一个 message 消息类型:

字段编号尽量使用 16 (虽然前15个 bytes 浪费了,但好处多多)

syntax = "proto3";

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}
  • 文件的第一行指明了我们使用的是 proto3 语法:若不指定该行 protocol buffer 编译器会认为是 proto2 。该行必须是文件的第一个非空或非注释行。
  • SearchRequest 消息定义了三个字段(名称/值对),字段就是每个要包含在该类型消息中的部分数据。每个字段都具有名称和类型 。

保留字段:

在采取彻底删除或注释掉某个字段的方式来更新消息类型时,将来其他用户再更新该消息类型时可能会重用这个字段编号。后面再加载该 .ptoto 的旧版本时会引发好多问题,例如数据损坏,隐私漏洞等。一个防止该问题发生的办法是将删除字段的编号(或字段名称,字段名称会导致在 JSON 序列化时产生问题)设置为保留项 reserved。protocol buffer 编译器在用户使用这些保留字段时会发出警告。

message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}

默认值:

当解析消息时,若消息编码中没有包含某个元素,则相应的会使用该字段的默认值。默认值依据类型而不同:

  • 字符串类型,空字符串
  • 字节类型,空字节
  • 布尔类型,false
  • 数值类型,0
  • 枚举类型,第一个枚举元素
  • 对于可重复类型字段的默认值是空的( 通常是相应语言的一个空列表 )。
  • 内嵌消息类型,依赖于所使用的编程语言。参考 generated code guide 获取详细信息。

注意一下标量字段,在消息被解析后是不能区分字段是使用默认值(例如一个布尔型字段是否被设置为 false )赋值还是被设置为某个值的。例如你不能通过对布尔值等于 false 的判断来执行一个不希望在默认情况下执行的行为。同时还要注意若一个标量字段设置为默认的值,那么是不会被序列化以用于传输的。

在 proto3 枚举值第一个字段必须是0:

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;
}