ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

proto3和proto2的区别

2021-06-29 19:00:46  阅读:710  来源: 互联网

标签:默认值 区别 default 语法 proto2 proto3 序列化


转自:https://solicomo.com/network-dev/protobuf-proto3-vs-proto2.html

proto3和proto2的区别


在粗略的看了 Protobuf 的文档中关于 proto2 和 proto3 的说明后,记录下了几点 proto3 区别于proto2的地方。
**总的来讲,proto3 比 proto2 支持更多语言但 更简洁。去掉了一些复杂的语法和特性,更强调约定而弱化语法。若是是首次使用 Protobuf ,建议使用 proto3 。**

1、在第一行非空白非注释行,必须写

    syntax = "proto3";

2、字段规则移除了 “required”,并把 “optional” 更名为 “singular”1;

在 proto2 中 required 也是不推荐使用的。proto3直接从语法层面上移除了required规则。
其实能够作的更完全,把全部字段规则描述都撤销,原来的repeated改成在类型或字段名后加一对中括号。
这样是否是更简洁? 

3、“repeated”字段默认采用 packed 编码;

在proto2 中,须要明确使用 [packed=true] 来为字段指定比较紧凑的 packed 编码方式。  

4、语言扩展

Go、Ruby、JavaNano 支持;google 

5、移除了 default 选项;

在 proto2 中,可使用 default
选项为某一字段指定默认值。在proto3中,字段的默认值只能根据字段类型由系统决定。也就是说,默认值所有是约
定好的,而再也不提供指定默认值的语法。

在字段被设置为默认值的时候,该字段不会被序列化。这样能够节省空间,提升效率。 但这样就没法区分某字段是根
本没赋值,仍是赋值了默认值。这在proto3 中问题不大,但在 proto2 中会有问题。

好比,在更新协议的时候使用 default 选项为某个字段指定了一个与原来不一样的默认值,旧代码获取到的该字段
的值会与新代码不同。

另外一个重约定而弱语法的例子是 Go 语言里的公共/私有对象。Go 语言约定,首字母大写的为公共对象,不然为私
有对象。因此在Go语言中是没有 public、private 这样的语法的。 

6、枚举类型的第一个字段必须为 0 ;这也是一个约定。

7、移除了对分组的支持;

分组的功能彻底能够用消息嵌套的方式来实现,而且更清晰。在 proto2中已经把分组语法标注为『过时』了。
此次也算清理垃圾了。 

8、旧代码在解析新增字段时,会把不认识的字段丢弃,再序列化后新增的字段就没了;

在 proto2 中,旧代码虽然会忽视不认识的新增字段,但并不会将其丢弃,再序列化
的时候那些字段会被原样保留。

我以为仍是 proto2 的处理方式更好一些。能尽可能保持兼容性和扩展能力,或许
实现起来也更简单。
proto3如今的处理方式,没有带来明显的好处,但丢掉了部分兼容性和灵活性。

[2017-06-15 更新]:通过漫长的讨论,官方终于赞成在 proto3 中恢复 
proto2 的处理方式了。能够经过这个文档了解来龙去脉及时间线。

9、移除了对扩展的支持,新增了 Any 类型;

Any 类型是用来替代 proto2 中的扩展的。目前还在开发中。

proto2 中的扩展特性很像 Swift 语言中的扩展。理解起来有点困难,使用起来更是会带来很多混乱。

相比之下,proto3 中新增的 Any 类型有点像 C/C++ 中的 void* ,好理解,使用起来逻辑也更清晰。

10、增长了 JSON 映射特性;

语言的活力来自于与时俱进。当前,JSON 的流行有其充分的理由。不少『现代化』的语言都内置了对 JSON 的支持,好比 Go、PHP
等。而 C++ 这种看似保罗万象的学院派语言,因循守旧、故步自封,以至于现出了式微的苗头。实际上,这样说并不许确,但这样理解起来更简单。 ```

本文编写时, Google 官方的 protobuf 版本是3.0.0beta

二、下面介绍下proto3的一些细节变化

Proto3的语法变化

1、语法标记

这个版本的protoc的protobuf编译器已经能够支持proto2语法和proto3的语法。
若是你的proto文件没有添加syntax说明的话, 用这个版本的编译器会报错, 提示你默认proto2支持, 请添加语法标记
syntax = "proto2";

2、optional不需要了

只保留repeated标记数组类型, optional和required都被去掉了
实际使用证实, required的设计确实是蛋疼, C++的调试版会弹出assert,release版和optional也没啥区别

3、map支持

map编写格式为

map<key_type, value_type> map_field = N; 
例如: 
map<string, Project> projects = 3; 
代码生成确认支持map, 这对于不少语言来讲又能够偷懒了 

4、字段default标记不能使用了

位于proto2语法的字段number后的[default=XX]
这个东西不能用了, 理由是:

对于同一段序列化后的数据, 若是序列化端的default和反序列化端的default描
述不同会致使最终结果彻底不一致
即: 同一个数据两个结果, 这是不可预测的结果, 所以干掉这个特性
不过本人以为, 对于游戏来讲, 这个功能自己能够压缩不少数据,虽然会有隐患

5、枚举默认值必定是0

proto2里的默认值是枚举的第一个value对应的值, 不必定为0
proto3在你定义value时, 强制要求第一个值必须为0
这个修改成避免隐患仍是有帮助的

6、泛型描述支持 any类型,

能够表明任何类型, 能够先读进来, 再进行解析, 没具体用, 步子跨大了怕扯到蛋

7、支持json序列化

这个极好, json再次被同化了

8、增长了多种语言支持

js, objc, ruby, C#等等
然而, C#版本的基础runtime库是用C# 6.0的语法写的,这对于Unity mono祖传2.0来讲, 确实扯到蛋了,无法用

9、Protobuf如今使用CMAKE作配置系统

编译起来稍微麻烦, 还要下个被墙掉的cmake…

10、第三方库里对于proto3的变化

Golang的官方protobuf支持:
https://github.com/golang/protobuf

标签:默认值,区别,default,语法,proto2,proto3,序列化
来源: https://blog.csdn.net/xuruilin1993/article/details/118340892

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有