相关教程

相关文献

区别

【精简版】(不想看全文的同学们可以看这里!!!)
【区别1】该文件的第一行指定您正在使用proto3语法:如果您不这样做,protocol buffer编译器将假定您使用的是proto2。这必须是文件的第一个非空、非注释行。
【区别2】proto3取消了proto2的required,而proto3的singular就是proto2的optional。
【区别3】proto3 repeated标量数值类型默认packed,而proto2默认不开启。
【区别4】proto3增加了Kotlin,Ruby,Objective-C,C#,Dart的支持
【区别5】proto2可以选填default,而proto3只能使用系统默认的。(序列化后如果是默认值是不会占用空间的,对于proto2来说处理就很麻烦了)
【区别6】proto3必须有一个零值,以便我们可以使用 0 作为数字默认值。零值需要是第一个元素,以便与proto2语义兼容,其中第一个枚举值始终是默认值。proto2则没有这项要求。
【区别7】proto3在3.5版本之前会丢弃未知字段。但在 3.5 版本中,重新引入了未知字段的保留以匹配 proto2 行为。在 3.5 及更高版本中,未知字段在解析过程中保留并包含在序列化输出中。
【区别8】proto3移除了proto2的扩展,新增了Any(仍在开发中)和JSON映射。

1. 定义消息类型(Defining A Message Type)

【proto2】:

message SearchRequest {
  required string query = 1;
  optional int32 page_number = 2;
  optional int32 result_per_page = 3;
}

【proto3】:

syntax = "proto3";

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

【区别】该文件的第一行指定您正在使用proto3语法:如果您不这样做,protocol buffer编译器将假定您使用的是proto2。这必须是文件的第一个非空、非注释行。

2. 指定字段规则(Specifying Field Rules)

【proto2】:

  • required:必须具有这个字段。
  • optional:可选字段。
  • repeated:可重复字段。

【proto3】:

  • singular:可以有零个或一个此字段(但不超过一个)。这是 proto3 语法的默认字段规则。
  • repeated:可重复字段。

【区别】proto3取消了proto2的required,而proto3的singular就是proto2的optional。

【proto2】:
由于历史原因,repeated标量数字类型(例如,int32, int64, enum)的字段编码效率不高。新代码应使用特殊选项[packed = true]以获得更有效的编码。例如:

repeated int32 samples = 4 [packed = true];
repeated ProtoEnum results = 5 [packed = true];

【proto3】:
在 proto3 中,repeated标量数值类型的字段packed默认使用编码。

【区别】proto3 repeated标量数值类型默认packed,而proto2默认不开启。

.proto会生成什么呢(What’s Generated From Your .proto?)

【proto2】:
C++, Java, Python, Go

【proto3】:
C++, Java, Kotlin, Python, Go, Ruby, Objective-C, C#, Dart

【区别】proto3增加了Kotlin,Ruby,Objective-C,C#,Dart的支持

默认值(Default Values)

【proto2】:

optional int32 result_per_page = 3 [default = 10];

【proto3】:

  • 对于字符串,默认值为空字符串。
  • 对于字节,默认值为空字节。
  • 对于 bool,默认值为 false。
  • 对于数字类型,默认值为零。
  • 对于enums,默认值是第一个定义的 enum value,它必须是 0。
  • 对于消息字段,未设置该字段。它的确切值取决于语言。有关详细信息,请参阅生成的代码指南。

【区别】proto2可以选填default,而proto3只能使用系统默认的。(序列化后如果是默认值是不会占用空间的,对于proto2来说处理就很麻烦了)

枚举(Enumerations)

【proto2】:

message SearchRequest {
  required string query = 1;
  optional int32 page_number = 2;
  optional int32 result_per_page = 3 [default = 10];
  enum Corpus {
    WEB = 1;
    IMAGES = 2;
    LOCAL = 3;
    NEWS = 4;
    PRODUCTS = 5;
    VIDEO = 6;
  }
  optional Corpus corpus = 4 [default = UNIVERSAL];
}

【proto3】:

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

【区别】proto3必须有一个零值,以便我们可以使用 0 作为数字默认值。零值需要是第一个元素,以便与proto2语义兼容,其中第一个枚举值始终是默认值。proto2则没有这项要求。

更新消息类型(Updating A Message Type)

【proto2】:
Any new fields that you add should be optional or repeated. This means that any messages serialized by code using your “old” message format can be parsed by your new generated code, as they won’t be missing any required elements. You should set up sensible default values for these elements so that new code can properly interact with messages generated by old code. Similarly, messages created by your new code can be parsed by your old code: old binaries simply ignore the new field when parsing. However, the unknown fields are not discarded, and if the message is later serialized, the unknown fields are serialized along with it – so if the message is passed on to new code, the new fields are still available.

【proto3】:
If you add new fields, any messages serialized by code using your “old” message format can still be parsed by your new generated code. You should keep in mind the default values for these elements so that new code can properly interact with messages generated by old code. Similarly, messages created by your new code can be parsed by your old code: old binaries simply ignore the new field when parsing. See the Unknown Fields section for details.

Unknown fields are well-formed protocol buffer serialized data representing fields that the parser does not recognize. For example, when an old binary parses data sent by a new binary with new fields, those new fields become unknown fields in the old binary.

Originally, proto3 messages always discarded unknown fields during parsing, but in version 3.5 we reintroduced the preservation of unknown fields to match the proto2 behavior. In versions 3.5 and later, unknown fields are retained during parsing and included in the serialized output.

【区别】proto3在3.5版本之前会丢弃未知字段。但在 3.5 版本中,重新引入了未知字段的保留以匹配 proto2 行为。在 3.5 及更高版本中,未知字段在解析过程中保留并包含在序列化输出中。(博主承认是懒得翻译全文了哈哈哈!!!)

扩展、任何、JSON 映射(Extensions & Any & JSON Mapping)

【proto2】:
扩展允许您声明消息中的一系列字段编号可用于第三方扩展。扩展名是原始.proto文件未定义类型的字段的占位符。这允许其他.proto文件通过定义具有这些字段编号的部分或全部字段的类型来添加到您的消息定义中。

【proto3】:
该Any消息类型,可以使用邮件作为嵌入式类型,而不必自己.proto定义。AnAny包含一个任意序列化的消息 as bytes,以及一个 URL,该 URL 充当全局唯一标识符并解析为该消息的类型。要使用该Any类型,您需要导入 google/protobuf/any.proto。
Proto3 支持 JSON 中的规范编码,从而更容易在系统之间共享数据。

【区别】proto3移除了proto2的扩展,新增了Any(仍在开发中)和JSON映射。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐