【超详细】Protobuf(Protocol Buffers)proto3 与 proto2 的区别——更新于2022.01

相关教程

相关文献

区别

【精简版】(不想看全文的同学们可以看这里!!!)
【区别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映射。

  • 8
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
***含了许多Google Protocol Buffers的头文件,其中也包括了google/protobuf/empty.proto。引用中提到在使用protoc进行编译时,报错找不到google/protobuf/empty.proto文件。而引用中提到解决这个问题的方法是在protoc的安装目录下创建一个软链接,将移动后的protobuf头文件目录连接到/usr/local/usr/include/google。综合这些信息,可以得出结论,google/protobuf/empty.proto是Google Protocol Buffers中的一个头文件,用于定义一个空的消息类型。如果在使用protoc进行编译时找不到该文件,可以尝试根据引用中提供的方法创建一个软链接以解决问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [protoc-3.4.0-win32](https://download.csdn.net/download/qq_40830236/10458935)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [记录一次protobuf的坑(google/protobuf/XXXXX.proto: File not found.)](https://blog.csdn.net/allenlake09/article/details/120741799)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值