当前位置: 首页 > news >正文

【ProtoBuf】杂记(默认值 | 更新规则 | 选项)

本篇博客记录 ProtoBuf 相关的杂碎知识点

文章目录

  • 默认值
  • 更新规则
    • reserved
  • 选项 option
    • 常用选项列举

默认值

在反序列化消息时,如果被反序列的二进制序列中不包含某个字段,反序列化对象中相应字段会设置为该字段的默认值。不同字段的默认值如下:

  • 字符串:默认为空串
  • 字节:默认为空字节
  • 布尔值:默认为 false
  • 数值类型:默认为 0
  • 枚举类:默认为第一个定义的枚举值,必须为0
  • 对于消息字段:取值依赖于语言
  • repeated 字段:默认是相应语言的一个空列表

PS:对于消息字段oneof字段any字段,C++ 和 Java 都有 has_ 方法检查当前字段是否被设置

更新规则

如果现有消息类型不符合现在的需求,例如需要扩展一个字段,在不破坏任何现有代码的情况下更新消息类型,遵循规则如下:

  • 禁止修改任何已有字段的字段编号
  • 若要移除老字段,要保证不再使用移除字段的字段编号。正确的做法是保留字段编号(reserved),以确保该编号将不再被重复使用。不建议直接删除或者注释掉字段
  • int32,uint32,int64,uint64 和 bool 是完全兼容的,可以从以上类型的一个改为另一个而不破坏前后兼容性。若解析出来的数值与相应类型不匹配,会采用与 C++ 一致的处理方案(例如,64位转32位,会进行截断)
  • sint32 和 sint64 相互兼容但不与其他整型兼容
  • string 和 bytes 在 UTF-8 下也兼容
  • bytes 包含消息编码版本的情况下,嵌套消息与 bytes 也兼容
  • fixed32 与 sfixed32 兼容,fixed64 与 sfixed64 兼容
  • oneof:
    • 将一个单独的值更改为新的 oneof 类型成员之一是安全和二进制兼容的
    • 若确定没有代码一次性设置多个值,那么将多个字段移入一个新的 oneof 类型也是可行的
    • 将任何字段移入已存在的 oneof 类型都是不安全的

reserved

如果通过删除或者注释字段来更新消息类型,未来的用户在添加新字段时,有可能会使用以前已经存在,但被删掉或者注释的字段编号,前后不同版本的字段但使用相同字段编号,会导致数据损坏
确保不会发生这种情况的一种方式:使用reserved将指定字段的编号或名称设置为保留项。当我们再使用这些编号或名称时,protobuf 编译器将会警告这些编号或名称不可用

例:

messageMessage{//设置保留项reserved 100, 101, 200 to 299;reserved "field3", "field4";//注意:不要在⼀⾏reserved声明中同时声明字段编号和名称。// reserved 102, "field5";// 设置保留项之后,下⾯代码会告警int32 field1 = 100;//告警:Field 'field1' uses reserved number 100int32 field2 = 101;//告警:Field 'field2' uses reserved number 101int32 field3 = 102;//告警:Field name 'field3' is reservedint32 field4 = 103;//告警:Field name 'field4' is reserved
}

选项 option

.proto 文件中可以声明许多选项,使用 option 标注。选项能影响 proto 编译器的某些处理方式

常用选项列举

选项的完整列表在 google/protobuf/descriptor.proto 中定义
选项有文件级,消息级,字段级等等

常用的选项如下:

  • optimize_for:该选项为文件选项,可以 protoc 编译器的优化级别,分别为 SPEEDCODE_SIZELIFE_RUNTIME。受该选项影响,设置不同的优化级别,编译 .proto 文件后生成的代码内容不同
    • SPEED:protoc 编译器将生成的代码是高度优化的,代码运行效率高,但由此生成的代码编译后会占用更多空间。SPEED是默认选项
    • CODE_SIZE:proto 编译器将生成最少的类,会占用更少空间,但代码运行效率较低,是依赖基于反射的代码实现序列化,反序列和各种其他操作。该方式适合用在包含大量 .proto文件,但并不盲目追求速度的应用中
    • LIFE_RUNTIME:生成的代码执行效率高,同时生成代码编译后的所占用空间也很少。该方式牺牲 反射 的功能,仅提供 encoding + 序列化功能,在编译时仅需链接 libprorobuf-lite。通常适用于资源有限的平台,例如移动手机平台
option optimize_for = LIFE_RUNTIME;
  • allow_alias:允许将相同的常量值分配给不同的枚举常量,用来定义别名。该选项为枚举选项
enum PhoneType{option allow_alias = true;MP = 0;TEL = 1;LANDLINE = 1;  //若不加选项,这一行会编译报错
}

以上就是本篇博客的所有内容,感谢你的阅读
如果觉得本篇文章对你有所帮助的话,不妨点个赞支持一下博主,拜托啦,这对我真的很重要。
在这里插入图片描述


http://www.mrgr.cn/news/53240.html

相关文章:

  • C++(stack和queue)
  • 第二十二篇——菲欧几何:相对论的数学基础是什么?
  • 【含文档】基于Springboot+Vue的出租车管理系统的设计与实现(含源码+数据库+lw)
  • 搭建知识库 | 知识管理在汽车行业中的作用
  • Python10.15作业
  • 解决flask_sqlalchemy代码不提示
  • 关于测试用例的写法
  • 汇编实现逆序复制数据
  • B2081 与 7 无关的数
  • 【开源项目】数字孪生智慧桥梁~虎门大桥——开放数据及源码
  • 【代码随想录Day45】动态规划Part13
  • 复习:如何理解 React 中的 fiber
  • 一键获取每日股票数据,自动更新,尽在掌握
  • 安全见闻笔记
  • [Gtk] 工程
  • OPENSSL-2023/11/10学习记录-C/C++对称分组加密DES
  • EPS导出DWG存在地物缺失或者没有编码属性的情况
  • float数据分别以int和float类型打印的反汇编分析
  • 【网络协议】之 HTTP 协议详解
  • 简单三步完成 Telegram 生态的 Web3 冷启动