protobuf中SerializeToString和SerializePartialToString的区别

2023-05-16

文章目录

  • 前言
  • proto2
    • message定义
    • message扩展
    • 注意事项
  • proto3
  • 序列化
    • SerializeToString和SerializeAsString区别
    • SerializeToString和SerializePartialToString区别
  • 总结

前言

protobuf是Google提出的序列化方案,此方案独立于语言和平台,目前提供了如c++、go、python等多种语言的实现,使用比较广泛,具有性能开销小,压缩率高等优点,是值得学习的优秀开源库。

protobuf有 v2 和 v3 两个主要的并且差异很大的版本,有一些关于protobuf的文章中并没有说明版本,有些描述的内容给人造成了疑惑,所以在使用protobuf前要明确自己使用的版本,查找对应的特性。

proto2

这个版本在编写 .proto 文件时的字段有三种限定符,分别是requiredoptionalrepeated

  • required:必须设置该字段,如果是在debug模式下编译 libprotobuf,则序列化一个未初始化(未对required字段赋值)的 message 将导致断言失败。在release模式的构建中,将跳过检查并始终写入消息,但解析未初始化的消息将返回false表示失败。
  • optional:可以设置也可以不设置该字段。如果未设置可选字段值,则使用默认值,也可以用[default = value]进行设置。
  • repeated:该字段可以重复任意次数(包括零次),可以将 repeated 字段视为动态大小的数组。

message定义

定义一个简单的 message 结构如下:

message Person {
  required string name = 1;
  optional string email = 2;
  optional int age = 3 [default = 18];
  repeated bytes phones = 4;
}

观察 message 定义可以看到每个字段后面都有 = 1= 2 的标记,这些被称为 Tags,在 protobuf 中同一个 message 中的每个字段都需要有独一无二的tag,tag 为 1-15 的是单字节编码,16-2047 使用2字节编码,所以1-15应该给频繁使用的字段。

关于tag的取值,还有一种范围是[1,536870911]的说法,同时 19000 到 19999 之间的数字也不能使用,因为它们是 protobuf 的实现中保留的,也就是 FieldDescriptor::kFirstReservedNumberFieldDescriptor::kLastReservedNumber 指定的范围,如果使用其中的数字,导出 .proto 文件时会报错,此处存疑,需要验证一下。

message扩展

在使用的了 protobuf 的项目发布以后,绝对会遇到扩展原有 message 结构的需求,这一点不可避免,除非发布后的项目不再升级维护了,要想扩展就需要兼容之前的代码逻辑,这里有一些必须遵守的规则,否则就达不到兼容的目的。

  • 不能更改任何现有字段的 tag
  • 不能添加或删除任何 required 字段
  • 可以删除 optional 或 repeated 的字段
  • 可以添加新的 optional 或 repeated 字段,但必须使用新的tag,曾经使用过又删除的 tag 也不能再使用了

注意事项

proto2 中对 required 的使用永远都应该非常小心。如果想在某个时刻停止写入或发送 required 字段,直接将字段更改为可选字段将会有问题。一些工程师得出的经验是,使用 required 弊大于利,他们更喜欢只使用 optional 和 repeated。

proto3

proto3 比 proto2 支持更多语言但更简洁,去掉了一些复杂的语法和特性。

  • 在第一行非空白非注释行,必须写:syntax = "proto3";
  • 直接从语法层面上移除了 required 规则,取消了 required 限定词
  • 增加了对 Go、Ruby、JavaNano 等语言的支持
  • 移除了 default 选项,字段的默认值只能根据字段类型由系统决定

序列化

将 message 结构对象序列化的函数有很多,即使是序列化成字符串也有多个函数可以使用,比如 SerializeToStringSerializePartialToStringSerializeAsStringSerializePartialAsString 等等。

SerializeToString和SerializeAsString区别

这两个还是很好区分的,从源码角度一眼就能够分辨出来:

std::string MessageLite::SerializeAsString() const {
  // If the compiler implements the (Named) Return Value Optimization,
  // the local variable 'output' will not actually reside on the stack
  // of this function, but will be overlaid with the object that the
  // caller supplied for the return value to be constructed in.
  std::string output;
  if (!AppendToString(&output)) output.clear();
  return output;
}

bool MessageLite::SerializeToString(std::string* output) const {
  output->clear();
  return AppendToString(output);
}

从源代码可以很容易看出,两者仅仅是参数和返回值的类型不同,其内部调用的函数都是一样的,SerializePartialToStringSerializePartialAsString 两个函数也是这种区别,可以根据外部逻辑所需来调用合适的函数。

bool MessageLite::SerializePartialToString(std::string* output) const {
  output->clear();
  return AppendPartialToString(output);
}

std::string MessageLite::SerializePartialAsString() const {
  std::string output;
  if (!AppendPartialToString(&output)) output.clear();
  return output;
}

SerializeToString和SerializePartialToString区别

这两个函数的区别在于内部调用的函数不同,一个调用 AppendToString,另一个调用 AppendPartialToString,两个被调用函数的源代码如下:

bool MessageLite::AppendToString(std::string* output) const {
  GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this);
  return AppendPartialToString(output);
}

bool MessageLite::AppendPartialToString(std::string* output) const {
  size_t old_size = output->size();
  size_t byte_size = ByteSizeLong();
  if (byte_size > INT_MAX) {
    GOOGLE_LOG(ERROR) << GetTypeName()
               << " exceeded maximum protobuf size of 2GB: " << byte_size;
    return false;
}

原来 AppendToString 函数调用了 AppendPartialToString, 只是在调用之前先执行了一句 GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this); 这句话什么意思呢?

其实就是一个调试状态下的检查,类似于 assert 这个断言函数吧,检查的内容是判断这个 message 是否初始化,之前提到 required 修饰的字段必须要设置一个值,否者就是未初始化的状态,那么现在两个函数的区别就知道了,带有 “Partial” 函数其实是忽略 required 字段检查的,另外还有没有别的不同需要再进一步研究下源码了。

总结

  • protobuf有 v2 和 v3 两个主要的并且差异较大的版本,使用前请注意版本号
  • proto3 直接从语法层面上移除了 required 规则,移除了 default 选项,字段的默认值只能根据字段类型由系统决定
  • SerializeToString和SerializeAsString区别在于参数和返回值的不同,内部调用的函数是相同的
  • SerializeToString和SerializePartialToString区别在于SerializePartialToString会忽略 required 字段必须赋值的要求
  • 在应用过程中尽可能重用 message 结构,这样protobuf内部实现中内存的重用

==>> 反爬链接,请勿点击,原地爆炸,概不负责!<<==

没有什么捷径,继续努力就好了
短期内不会看到什么成果,甚至说一辈子都可能看不到,但只有努力了才有可能看得到

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

protobuf中SerializeToString和SerializePartialToString的区别 的相关文章

  • Netty使用Google Protobuf进行编解码

    文章目录 一 概述1 编解码基础2 Netty编解码器3 Protobuf概述 二 Protobuf基本使用1 引入jar包2 下载Protobuf3 编写Student proto4 生成StudentPOJO类5 服务器端6 客户端7
  • protobuf中SerializeToString和SerializePartialToString的区别

    文章目录 前言proto2message定义message扩展注意事项 proto3序列化SerializeToString和SerializeAsString区别SerializeToString和SerializePartialToSt
  • 编译protobuf v3.20.0

    https github com protocolbuffers protobuf git clone git 64 github com protocolbuffers protobuf git cd protobuf git check
  • 使用Zeromq和protobuf实现的socket通信

    本文介绍使用ZeroMQ 下文简称ZMQ 结合protobuf序列化实现客户端和服务端的通信 在之前的一篇文章中 http blog csdn net cjf wei article details 52894560 介绍了Google的p
  • ZeroMQ+Protobuf实例

    使用库版本 zeromq 4 0 3 接收端代码 include lt zmq h gt include 34 stdio h 34 int main int argc char argv void pCtx 61 NULL void pS
  • ProtoBuf 与 gRPC 你需要知道的知识

    ProtoBuf 是一套接口描述语言 xff08 IDL xff09 和相关工具集 xff08 主要是 protoc xff0c 基于 C 43 43 实现 xff09 xff0c 类似 Apache 的 Thrift xff09 用户写好
  • 【ProtoBuf】ProtoBuf 通过 proto 文件生成 cc/h 文件

    参考 xff1a protobuf ProtoBuf 通过 proto 文件生成 cc h 文件的步骤如下 xff08 Linux 下 xff09 xff1a 先通过 protobuf 源文件编译出 protoc 可执行文件 span cl
  • protobuf快速上手

    protobuf快速上手 一 序列化与反序列化 序列化与反序列化的场景 常用的工具 二 protobuf工作原理 三 快速上手 protobuf中的数据类型 proto文件格式 编译选项 快速上手 四 通讯录demo 编写proto文件 编
  • protobuf的序列化和反序列化的分析

    一 protobuf的optional 数据类型序列化分析 1 optional 的protobuf的文件 格式 syntax proto2 message test proto optional int32 proto1 1 option
  • protobuf下载与安装+ protobuf 与json相互转换方法

    WIN环境 下载与安装 下载 https github com protocolbuffers protobuf releases 官方git地址 目前最新的是3 8版本 我是c 环境 选择cpp下载包 protobuf cpp 3 8 0
  • protobuf 2.0版本排查必填字段未填的方法

    在proto2 0版本中 如果required字段没有填写 那么proto编码字符串发给对方进行parse时 对方会parse失败 因此有必要在发送前检查一下是否存在这种情况 特别是在debug阶段 1 为了获取proto序列化的错误信息
  • proto文件生成教程

    来源 https www cnblogs com jbw752746541 p 10973200 html 首先贴一下Protobuf各个版本历史下载链接 https github com protocolbuffers protobuf
  • protobuf生成prototxt文件

    使用protobuf可以分为以下几步 1 proto文件的定义 在这个文件中定义了最终生成的prototxt格式 举个例子如下所示 syntax proto2 package label proto message DetectLabel
  • protobuf 中复合数据类型的读写

    背景 protobuf 在生成的 C 代码中为 proto 文件中的每个 message 生成了对应的 C 类 并提供了数据成员的读写方法 message 类型读写 message 示例 message Point double lng 1
  • protobuf-IOS简单总结(编译、环境搭建)

    什么是protobuf Protocol Buffers are a way of encoding structured data in an efficient yet extensible format Google uses Pro
  • Protobuf在java中的简单使用实例

    TTprotobuf是一种跨语言的数据转换协议 由google开源的 已支持大部份语言 在一般的数据交互过程中都是使用json xml等来做数据的转换 这其中涉及复杂的解析与序列化反序列化问题 如果在大量数据并发请求时 也会导致性能问题 p
  • 实战搞定gRPC之移植篇

    一 交叉编译protobuf 1 配置交叉编译器 export PATH PATH opt EC20 crosstool ql ol crosstool sysroots x86 64 oesdk linux usr bin opt EC2
  • Protobuf(二)proto3语法格式

    proto文件有两种语法标准 proto2和proto3 我们以proto3为例 其语法格式如下 message
  • 2. IDEA + maven + protobuf配置(on mac)

    1 絮絮叨叨 都说懒惰是人类进步的源泉 有时候想想还真就那么回事 学习了如何使用protoc命令编译 重度依赖IDEA且已经习惯了maven的我 就在想是否能在IDEA中一键编译 proto文件 2 vscode配置protobuf编辑环境
  • Protobuf安装步骤

    今天看Brpc开源代码的时候 看到了里面提到了google开源的protobuf的数据序列化和反序列工具 所以特地下了源码 试着看下一个简单的使用过程 1 protobuf的介绍 google protobuf是一个灵活的 高效的用于序列化

随机推荐

  • MySQL分组查询语句

    文章目录 1 需求2 表结构与部分数据3 查询语句4 结果5 前端显示 1 需求 根据账单表 tb bookkeeping 中的用户ID user id xff0c 按时间倒序查询该用户所在房间所有支出 xff08 bk type 61 0
  • 使用pyinstaller将具有多个python文件的项目打包为exe(含依赖库)

    1 将需要打包有python文件放到一个文件夹 xff0c 例如下图所示的Demo文件夹 xff0c 其中ClickEveryDay py为主文件 xff0c telegram ico为图标文件 2 生成主函数对应的spec文件 命令 xf
  • 在win10下使用PowerShell批量替换文件名

    步骤 通过PowerShell ISE来创建扩展名为 ps1的脚本文件 具体操作过程参考 xff1a https www ithome com html win10 250196 htm编辑新建的 ps1文件 xff0c 举个栗子进行简单说
  • Kotlin笔记15——字符串转数字类型

    前言 在使用Java编程语言开发的 xff0c 我们会经常遇到字符串转数字的需求 那么在Kotlin中是怎么实现的呢 xff1f 接下来跟大家分享一下 字符串转数字 首先我们必须保证字符串是数字类型 xff0c 不能出现a3这种数字与字符混
  • 使用gitLab过程中遇到的一些问题

    之前由于疫情 xff0c 电脑放在公司 xff0c 有一些数据需要其他同事帮忙提交 xff0c 怎知居然连了他的git账号 xff0c 搞得我自己代码提交拉取老有问题 xff0c 一开始没有意识到是这个原因 xff0c 知道打开了自己git
  • 【Micropython】肝货~使用USB_VCP通过USB串口与树莓派或PC端通信

    为什么要使用USB VCP xff1f Micropython有很多串口 xff0c 例如PYboard xff0c 有5个串口可以使用 xff0c 但是 xff0c 平时我们在做一些项目的时候 xff0c 需要使用的引脚较多 xff0c
  • ROS中安装配置并使用VScode(持续更新)

    1 为什么使用VScode VSCode 全称 Visual Studio Code xff0c 是微软出的一款轻量级代码编辑器 xff0c 免费 开源而且功能强大 它支持几乎所有主流的程序语言的语法高亮 智能代码补全 自定义热键 括号匹配
  • pip install airsim问题

    直接使用pip install airsim安装airsim包会失败 airsim C Users DELL gt pip install airsim Collecting airsim Using cached airsim 1 8 1
  • vm虚拟机无法拖拽文件和复制粘贴解决办法

    sudo apt install open vm tools sudo apt install open vm tools desktop
  • PX4和Airsim通信操作流程

    坑真几把多 先在Windows上安装UE4和Airsim不再赘述 xff0c 官网都有 虚拟机或其他计算机安装好ubuntu并安装PX4 1 安装PX4的ROS相关包 xff08 mavros xff09 1 第一种 xff1a 进入官网安
  • mavros安装流程(超简单)

    只适用于Ubuntu18 04 在Ubuntu中新建一个空白文本 xff0c 命名为123 sh bin bash Bash script for setting up ROS Melodic with Gazebo 9 developme
  • 安装WSL2+Ubuntu18.04(慢慢更新记录)

    1 安装WSL和Ubuntu WSL官网在此 安装 WSL Microsoft Learn Windows下CMD xff0c 先安装WSL2 wsl install 然后进入Microsoft Store xff0c 搜索Ubuntu然后
  • -bash: ./Setup.sh: Permission denied

    sudo chmod 777 xxx
  • Linux 给文件夹或者文件添加权限

    chmod R 777 文件夹 参数 R是递归的意思 777表示开放所有权限 chmod 777 test sh chmod 43 x 某文件 如果给所有人添加可执行权限 xff1a chmod a 43 x 文件名 xff1b 如果给文件
  • Postman使用笔记——Postman发送get请求

    前言 在实际的开发当中 xff0c 我们经常用到get或者post请求 在这篇博客里面分享一下 xff0c 如何在Postman中发送get请求 发送get请求 1 在Postman工作空间选定get请求 图中我们可以看到很多请求方式 xf
  • jdbc连接mysql数据库的详细步骤

    标题 jdbc连接mysql数据库 1 首先在项目根目录创lLib文件夹 xff0c 放入jdbc驱动程序 xff0c 然后Add As Library 2 建包 bean包 xff1a 专门放置属性类 dao包 xff1a 进行数据操作的
  • css高度从0到auto的transition动画

    如题 xff0c 想实现css高度从0到auto的transition动画 xff0c 发现直接写没有效果 查了一下 xff0c 发现可以用max height解决 xff0c 代码如下 lt DOCTYPE html gt lt html
  • beego打包

    beego打包 在main go 对应的目录下 windows平台 xff1a bee pack be GOOS 61 windows 打包后生成一个tar gz文件 xff0c 发送到部署服务器 xff0c 解压gz为tar xff0c
  • C++求解组合数的具体实现

    文章目录 前言问题起因组合公式公式变形递推公式递归实现备忘递归动态规划压缩DP其他优化 总结补充反向递归正向递推 前言 很少写关于具体算法的总结笔记 xff0c 因为很难把一个算法从头到尾的叙述清晰并且完整 xff0c 容易造成误解 这次想
  • protobuf中SerializeToString和SerializePartialToString的区别

    文章目录 前言proto2message定义message扩展注意事项 proto3序列化SerializeToString和SerializeAsString区别SerializeToString和SerializePartialToSt