[Protobuf]常见数据类型以及使用注意事项

article/2025/8/3 20:02:27

[Protobuf]常见数据类型以及使用注意事项
@水墨不写bug


在这里插入图片描述


文章目录

  • 一、基本数据类型
    • 1、字段
    • 2、字段的修饰规则
  • 二、自定义数据类型
    • 1、message类型
    • 2、enum类型
    • 3、Any类型
    • 4、oneof类型
    • 5、map类型
  • 三、小工具
    • 1.hexdump
    • 2.decode
  • 四、注意事项


一、基本数据类型

protobuf 支持多种基础数据类型,常用的有:

类型说明可选值范围(部分)
double64位浮点数±1.7E±308
float32位浮点数±3.4E±38
int32使用变长编码[1]。负数的编码效率较低⸺若字段可能为负值,应使用 sint32 代替-2^31 到 2^31-1
int64使用变长编码[1]。负数的编码效率较低⸺若字段可能为负值,应使用 sint64 代替-2^63 到 2^63-1
uint32无符号32位整型 ,使用变长编码[1]0 到 2^32-1
uint64无符号64位整型 ,使用变长编码[1]0 到 2^64-1
sint32有符号32位整型(高效编码负数)-2^31 到 2^31-1
sint64有符号64位整型(高效编码负数)-2^63 到 2^63-1
fixed32定长 4 字节。若值常大于2^28 则会比 uint32 更高效。0 到 2^32-1
fixed64定长 8 字节。若值常大于2^56 则会比 uint64 更高效。0 到 2^64-1
sfixed32固定32位有符号整型(固定长度编码)-2^31 到 2^31-1
sfixed64固定64位有符号整型(固定长度编码)-2^63 到 2^63-1
bool布尔值true/false
string包含 UTF-8 和 ASCII 编码的字符串,长度不能超过 2^32任意长度字符串
bytes可包含任意的字节序列但长度不能超过 2^32任意长度字节数组

注:[1] 变长编码是指:经过protobuf 编码后,原本4字节或8字节的数可能会被变为其他字节数


1、字段

在定义一个字段之后,会给字段设置一个唯一标记值同一个消息体内,字段标记值不能重复。

message PersonInfo
{int id = 1;string name = 1;//(字段标志重复)
}

消息体内的消息体可以重新计算标记值:

message PersonInfo
{int id = 1;string name = 2;message Phone{string number = 1;//(重新计算标记值)}
}

其次:

字段名称命名规范:全小写字母,多个字母之间用 _ 连接。
字段类型分为:基本数据类型 和 特殊类型(包括枚举enum、消息类型message等)。
字段唯⼀编号:用来标识字段,⼀旦开始使用就不能够再改变

字段编号的范围为:

1 ~ 536,870,911 (2^29 - 1) ,其中 19000 ~ 19999 不可用

范围为 1 ~ 15 的字段编号需要一个字节进行编码, 16 ~ 2047内的数字需要两个字节进行编码。编码后的字节不仅只包含了编号,还包含了字段类型。所以 1 ~ 15要用来标记出现非常频繁的字段,要为将来有可能添加的、频繁出现的字段预留一些出来。

2、字段的修饰规则

singular:消息中可以包含该字段零次或⼀次(不超过⼀次)。 proto3 语法中,字段默认使用该规则。
repeated:消息中可以包含该字段任意多次(包括零次),其中重复值的顺序会被保留。可以理解为定义了⼀个数组。


二、自定义数据类型

1、message类型

一个message类型被protoc编译器编译之后形成对应class。message可以嵌套message,同一层message,字段编号不能重复。message可作为类型来使用,对应class类型组合。

2、enum类型

定义enum类型的值,直接用名称+常量表示:
例如:

enum PhoneType //枚举名称的名称建议用驼峰命名
{MP = 0;TEL = 1;
}

常量值从0开始,只能为正值,不能为负。枚举类型也可定义在message体内部。

在同一层级内,不同的枚举类型内的同名常量值不能相同:
例如:

enum PhoneType
{MP = 0;TEL = 1;
}
enum PhoneTypeCopy
{MP = 0;
}

否则会报错重定义。
改为不重名即可:

enum PhoneType
{MP = 0;TEL = 1;
}
enum PhoneTypeCopy
{MP_C = 0;
}

类似的还有两个没有限制package的文件,import后也会出现上述类似问题。
解决方法是加上package限制。

3、Any类型

泛型类型,可以存放任意类型的数据。
是google直接写好的,使用前需要

import "google/protobuf/any.proto";

声明变量的格式如下:

message PeopleInfo
{google.protobuf.Any data = 0;
}

使用any类型需要常用的接口:

// .google.protobuf.Any data = 4;
bool has_data() const;//是否有数据
void clear_data();//清除数据
const ::PROTOBUF_NAMESPACE_ID::Any& data() const;//get
::PROTOBUF_NAMESPACE_ID::Any* mutable_data();//set
//把任意类型转化为any类型
bool PackFrom(const ::PROTOBUF_NAMESPACE_ID::Message& message);
//重载类型
bool PackFrom(const ::PROTOBUF_NAMESPACE_ID::Message& message,::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url_prefix);
//把any类型转化为任意类型
bool UnpackTo(::PROTOBUF_NAMESPACE_ID::Message* message) const;
//判断Any类型是否是T类型
template<typename T> bool Is() const {return _impl_._any_metadata_.Is<T>();}

4、oneof类型

被oneof声明的多个字段只能保留最后被设置的一个:

oneof other_contact
{string qq = 5;string wechat = 6;
}

qq和微信字段只会保留最后一次被设置的值。

oneof内部不能使用repeated修饰字段。

常用方法包括clear,set,get。不同的是多了一个has方法,用来表明是否有这个方法。

在对应生成的Cpp代码中,oneof类型定义的多个类型会被转化为一个enum类型。内部除了oneof内部的类型之外,还有一个NOT_SET = 0常量值。

5、map类型

类似于C++的map,定义protobuf的map需要注意,key_type只能是float,bytes类型之外的标量类型。val_type可以是任意类型。
map不能被repeated修饰。
设置的key-val键值对是无序的。

常用方法:size,clear,get,set。


三、小工具

1.hexdump

hexdump是Linux下的⼀个二进制文件查看工具,它可以将二进制文件转换为ASCII、八进制、十进制、十六进制格式进行查看。
-C: 表示每个字节显示为16进制和相应的ASCII字符

这个工具意义在于把protobuf序列化后的二进制转化为ASCII,便于查看。

2.decode

ProtoBuf 提供的一个命令选项 --decode ,表表示从标准输入中读取给定类型的二进制消息,并将其以文本格式写入标准输出。 消息类型必须在 .proto 文件或导入的文件中定义。
在这里插入图片描述

protoc --decode=contacts.Contacts contacts.proto < contacts.bin

这条命令用于解码一个用 Protocol Buffers(protobuf)序列化后的二进制文件 contacts.bin,并将其内容以可读的文本格式输出。下面是这条命令的详细解释:

  1. protoc
    这是 Protocol Buffers 的编译器命令行工具,用于编译 .proto 文件和处理 protobuf 数据。

  2. –decode=contacts.Contacts
    这个参数的意思是用 .proto 文件中定义的 contacts.Contacts 这个消息类型来解码输入的数据。

    • contacts 是 proto 文件中的包名(package)。
    • Contacts 是 proto 文件中定义的消息类型(message)。
  3. contacts.proto
    这是 protobuf 的协议文件,里面定义了数据结构(消息类型、包名等)。protoc 会用它来知道怎么解析二进制数据。

  4. < contacts.bin
    这表示将 contacts.bin 文件中的二进制数据(用 protobuf 序列化过的)作为标准输入传给 protoc


四、注意事项

  1. 字段编号(tag)不可轻易变更
    字段编号 是二进制格式的唯一标识,不能随意修改或复用,否则会导致兼容性问题。

  2. 尽量避免删除字段
    如果需要废弃字段,可用 reserved 关键字保留该 tag 和字段名。

  3. 字段类型不能随意更改
    特别是从一种类型改为不兼容的另一种类型(如 int32 改为 string),会导致解析错误。

  4. repeated 字段适合表达数组或列表
    表示 0 个或多个同类型数据项。例如 repeated int32 scores。

  5. 嵌套 message 和 enum
    可以在 message 内部定义子 message 或 enum,便于结构化复杂数据。

  6. 避免使用 float/double 存储精确金额
    由于浮点数精度问题,金额等精确数据建议用 int64/uint64 表示最小单位(如分、厘)。

  7. bytes 与 string 区别
    string 专为 UTF-8 文本,bytes 则可存储任意二进制数据,如图片、加密内容等。


完~
未经作者同意禁止转载
在这里插入图片描述



http://www.hkcw.cn/article/NjlLCTDijF.shtml

相关文章

邂逅Webpack和打包过程

前端开发方向 目前国内的前端开发 主要使用Vue和React 一般你写个项目&#xff0c;过程就是&#xff1a;npm/yarn --> webpack架构 --> Vue/React框架 而针对Vue和React都有脚手架的&#xff0c;脚手架是基于webpack搭建的 你写.jsx或者ts之类的浏览器是不认识的&…

计算机网络第1章(下):网络性能指标与分层模型全面解析

目录 一、计算机网络的性能指标1.1 性能指标1&#xff1a;速率1.2 性能指标2&#xff1a;带宽1.3 性能指标3&#xff1a;吞吐量1.4 性能指标4&#xff1a;时延1.5 性能指标5&#xff1a;时延带宽积1.6 性能指标6&#xff1a;往返时延1.7 性能指标7&#xff1a;信道利用率 二、计…

多模态大语言模型arxiv论文略读(102)

Chat2Layout: Interactive 3D Furniture Layout with a Multimodal LLM ➡️ 论文标题&#xff1a;Chat2Layout: Interactive 3D Furniture Layout with a Multimodal LLM ➡️ 论文作者&#xff1a;Can Wang, Hongliang Zhong, Menglei Chai, Mingming He, Dongdong Chen, Ji…

python学习打卡day42

DAY 42 Grad-CAM与Hook函数 知识点回顾 回调函数lambda函数hook函数的模块钩子和张量钩子Grad-CAM的示例 作业&#xff1a;理解下今天的代码即可 1.回调函数 Hook本质是回调函数&#xff0c;所以我们先介绍一下回调函数 回调函数是作为参数传递给其他函数的函数&#xff0…

VeriFree:无需Verifier的通用RL框架

文章目录 前言1. 研究背景与挑战1.1 传统强化学习框架&#xff08;RLVR&#xff09;的领域局限性1.2 引入LLM作为验证器的新挑战1.3 研究目标的提出 2. VeriFree方法核心原理2.1 问题定义与形式化建模2.2 核心思想&#xff1a;隐式验证与概率最大化2.3 训练技术细节 3. 实验4. …

uniapp uni-id 如果是正式项目,需自行实现发送邮件的相关功能

(3) 使用云对象sendEmailCode 发送邮箱验证码&#xff0c;报错送邮箱验证码失败 Error: 已启动测试模式&#xff0c;直接使用&#xff1a;123456作为邮箱验证码即可。 如果是正式项目&#xff0c;需自行实现发送邮件的相关功能 - DCloud问答 uni-id 没有实现邮箱验证码逻辑&am…

HiEV独家 | 整合智能化战线,奇瑞辅助驾驶驶向何方?

作者 |德新 编辑 |王博 组织调整是战略变革的映射&#xff0c;而战略变革最终要在产品上体现。 5月30日&#xff0c;奇瑞汽车官宣整合旗下雄狮科技、大卓智能与研发总院相关业务&#xff0c;成立「智能化中心」。智能化中心下设有智能座舱、智能辅助驾驶、电子电气架构等子中…

什么是软件需求可视化?如何实际运用?

一、什么是软件需求可视化&#xff1f; 将软件需求可视化是一个有助于团队成员更好地理解项目需求、促进沟通和协作的重要过程。以下是几种常见的方法和技术&#xff0c;可以帮助你有效地实现这一目标&#xff1a; 用户故事地图&#xff1a;这是一种通过创建一个从用户角度出发…

腾讯:强化学习提高LLM机器翻译

&#x1f4d6;标题&#xff1a;TAT-R1: Terminology-Aware Translation with Reinforcement Learning and Word Alignment &#x1f310;来源&#xff1a;arXiv, 2505.21172 &#x1f31f;摘要 最近&#xff0c;像DeepSeek-R1这样的深度推理大型语言模型&#xff08;LLM&…

C++ IO流

目录 一、C语言的输入与输出 二、流 三、CIO流 3.1 C标准IO流 3.2 C文件IO流 3.3 stringstream字符串流 一、C语言的输入与输出 在 C 语言中&#xff0c;最常用的输入输出函数是 scanf() 和 printf()。它们分别用于从标准输入读取数据&#xff0c;以及将数据输出到标准输出…

linux文件管理(补充)

1、查看文件命令 1.1 cat 用于连接文件并打印到标准输出设备上&#xff0c;它的主要作用是用于查看和连接文件。 用法&#xff1a; cat 参数 文件名 参数&#xff1a; -n&#xff1a;显示行号&#xff0c;会在输出的每一行前加上行号。 -b&#xff1a;显示行号&#xff0c;…

Relational Algebra(数据库关系代数)

目录 What is an “Algebra” What is Relational Algebra? Core Relational Algebra Selection Projection Extended Projection Product&#xff08;笛卡尔积&#xff09; Theta-Join Natural Join Renaming Building Complex Expressions Sequences of Assignm…

操作系统:进程管理(王道+计算机操作系统)

第二章 进程与线程 2.1进程的概念、组成与特征 2.1.1 进程与程序的区别 ​ 1.程序&#xff1a;静态的&#xff0c;就是放在磁盘里的可执行文件&#xff0c;如&#xff1a;QQ.exe。 ​ 2.进程&#xff1a;动态的&#xff0c;是程序的一次执行过程&#xff0c;如&#xff1a;…

浅谈简历制作的四点注意事项

如大家所了解的&#xff0c;一份工作&#xff0c;往往是从制作一份简历开始。 对于新人来说&#xff0c;简历制作的注意事项&#xff0c;你又了解多少呢&#xff1f;下面一起来看看吧&#xff01; 简历字数&#xff1a;一封合格的简历字数大概在 350 词 – 650 词之间&#xf…

软考-数据库系统工程师-程序设计语言知识要点

小房学堂&#xff0c;程序设计语言知识要点 汇编、编译、解释系统的基础知识 计算机只能理解由0-1组成的指令&#xff0c;就像一个只会本国语言的人&#xff0c;他听不懂其他国家的语言 而程序员编程使用的是低级语言&#xff08;汇编语言&#xff09;或者高级语言如C、C、Jav…

6级翻译学习

找到一个中文句子先看中文句子的主谓宾&#xff0c;主系表 不会写的词不要写&#xff0c;不会影响得分&#xff0c;只要其他地方写对

【Rhino】【Python】adjust repeated column marks

#codingutf-8 import rhinoscriptsyntax as rs import re import System.Guiddef process_column_marks():# 获取目标图层中的所有文本对象layer_name "03 STR. DRAFT MEMBER::COLUMN MARK"text_objects rs.ObjectsByLayer(layer_name, True)if not text_objects o…

Goreplay最新版本的安装和简单使用

一&#xff1a;概述 Gor 是一个开源工具&#xff0c;用于捕获实时 HTTP 流量并将其重放到测试环境中&#xff0c;以便使用真实数据持续测试您的系统。它可用于提高对代码部署、配置更改和基础设施更改的信心。简单易用。 项目地址&#xff1a;buger/goreplay: GoReplay is an …

YOLOv5 环境配置指南

系统要求 Windows/Linux/MacOSNVIDIA GPU (推荐) 或 CPUPython 3.8CUDA 11.8 (如果使用 GPU) 安装步骤 1. 安装 Conda 如果还没有安装 Conda&#xff0c;请先从官网下载并安装 Miniconda。 2. 创建虚拟环境 # 创建名为 yolov5 的新环境&#xff0c;使用 Python 3.8 conda…

【算法应用】虚拟力算法VFA用于WSN覆盖,无人机网络覆盖问题

目录 1.虚拟力算法VFA2.WSN覆盖&无人机覆盖应用3.参考文献4.代码获取5.读者交流 1.虚拟力算法VFA 虚拟势场&#xff08;Virtual Potential Field&#xff09;最早因解决机器人路径规划及避障问题而被提出。它假设待优化个体会根据某种关系与周围的环境或其他个体产生力的作…