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

[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.pswp.cn/diannao/85331.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JS分支和循环

程序的执行顺序 在程序开发中&#xff0c;程序有三种不同的执行顺序 1.顺序执行 2.分支执行 3.循环执行 程序的代码块 <script>//一个代码块{var num11var num22var num3num1num2}//一个休想var info{name:"chen",age:18} 1.if分支语句&#xff08;单分支语句&…

Android 开发 Kotlin 全局大喇叭与广播机制

在 Android 开发中&#xff0c;广播机制就像一个神通广大的 “消息快递员”&#xff0c;承担着在不同组件间传递信息的重任。Kotlin 语言的简洁优雅更使其在广播机制的应用中大放异彩。今天&#xff0c;就让我们一同深入探索 Android 开发中 Kotlin 全局大喇叭与广播机制的奥秘…

rabbitmq AI复习

RabbitMq rabbitmq &#x1f9d1;‍&#x1f4bb; User 帮我复习rabbitmq相关知识&#xff0c;我是一个经验丰富的程序员 &#x1f916; Assistant 好的&#xff01;很高兴能通过这种方式帮你复习或学习 RabbitMQ 的知识。按照你说的流程&#xff0c;我们从完全零基础开始&…

计算机视觉---YOLOv5

YOLOv5理论讲解 一、YOLOv5 整体架构解析 YOLOv5 延续了 YOLO 系列的 单阶段目标检测框架&#xff0c;包含 主干网络&#xff08;Backbone&#xff09;、颈部网络&#xff08;Neck&#xff09; 和 检测头&#xff08;Head&#xff09;&#xff0c;但在结构设计上更注重 轻量化…

C++多重继承详解与实战解析

#include <iostream> using namespace std; //基类&#xff0c;父类 class ClassA { public:void displayA() {std::cout << "Displaying ClassA" << std::endl;}void testFunc(){std::cout << "testFunc ClassA" << std::e…

单细胞注释前沿:CASSIA——无参考、可解释、自动化细胞注释的大语言模型

细胞类型注释是单细胞RNA-seq分析的重要步骤&#xff0c;目前有许多注释方法。大多数注释方法都需要计算和特定领域专业知识的结合&#xff0c;而且经常产生不一致的结果&#xff0c;难以解释。大语言模型有可能在减少人工输入和提高准确性的同时扩大可访问性&#xff0c;但现有…

STM32Cubemx-H7-17-麦克纳姆轮驱动

前言 --末尾右总体的.c和.h 本篇文章把麦克纳姆轮的代码封装到.c和.h&#xff0c;使用者只需要根据轮子正转的方向&#xff0c;在.h处修改定义方向引脚&#xff0c;把轮子都统一正向后&#xff0c;后面的轮子驱动就可以正常了&#xff0c;然后直接调用函数驱动即可。 设置满…

文档核心结构优化(程序C++...)

文档核心结构优化 一、文档核心结构优化二、C关键特性详解框架2.1 从C到C的范式迁移 三、深度代码解析模板3.1 现代C特性分层解析 四、C vs C 关键差异矩阵五、交互式文档设计策略5.1 三维学习路径5.2 代码缺陷互动区 六、现代C特性演进图七、性能优化可视化呈现&#xff08;深…

PyTorch ——torchvision数据集使用

如果下载的很慢&#xff0c;可以试试下面这个

纯前端实现图片伪3D视差效果

作者&#xff1a;vivo 互联网前端团队- Su Ning 本文通过depth-anything获取图片的深度图&#xff0c;同时基于pixi.js&#xff0c;通过着色器编程&#xff0c;实现了通过深度图驱动的伪3D效果。该方案支持鼠标/手势与手机陀螺仪双模式交互&#xff0c;在保证性能的同时&#x…

英语写作中“专注于”focus on、concentrate的用法

Focus on在论文写作中常用&#xff0c;指出研究点&#xff0c;例如&#xff1a; There are three approaches to achieving ID authentication. Our study will focus on ……&#xff08;有三种途径实现身份认证&#xff0c;我们的研究专注于……&#xff09; concentrate &…

go环境配置

下载对应版本的 go 版本 https://go.dev/dl/ 配置 vim ~/.zshrc export GOROOT/usr/local/go export PATH$PATH:$GOROOT/binsource ~/.zshrc >>>>>> go versiongoland 配置&#xff1a; &#x1f50d; 一、什么是GOPATH&#xff1f; GOPATH 是旧的项目结…

AI Agent智能体:底层逻辑、原理与大模型关系深度解析·优雅草卓伊凡

AI Agent智能体&#xff1a;底层逻辑、原理与大模型关系深度解析优雅草卓伊凡 一、AI Agent的底层架构与核心原理 1.1 AI Agent的基本构成要素 AI Agent&#xff08;人工智能代理&#xff09;是一种能够感知环境、自主决策并执行行动的智能系统。其核心架构包含以下关键组件…

【手搓一个原生全局loading组件解决页面闪烁问题】

页面闪烁效果1 页面闪烁效果2 封装一个全局loading组件 class GlobalLoading extends HTMLElement {constructor() {super();this.attachShadow({ mode: open });}connectedCallback() {this.render();this.init();}render() {this.shadowRoot.innerHTML <style>.load…

unix/linux source 命令,其高级使用

就像在物理学中,掌握了基本定律后,我们可以开始研究更复杂的系统和现象,source 的高级用法也是建立在对其基本行为深刻理解之上的。 让我们一起探索 source 的高级应用领域: 1. 条件化加载 (Conditional Sourcing) 根据某些条件来决定是否 source 一个文件,或者 source…

DexGarmentLab 论文翻译

单个 专家 演示 装扮 15 任务 场景 2500+ 服装 手套 棒球帽 裤子 围巾 碗 帽子 上衣 外套 服装-手部交互 捕捉 摇篮 夹紧 平滑 任务 ...... 投掷 悬挂 折叠 ... 多样化位置 ... 多样化 变形 ... 多样化服装形状 类别级 一般化 类别级(有或没有变形) 服装具有相同结构 变形 生…

WPF-Prism学习笔记之 “导航功能和依赖注入“

新建空白模板(Prism) 新建好后会有自动创建ViewModels和Views 在"MainWindow.xaml"文件里面标题去绑定了一个属性"Title"&#xff0c;而"MainWindowViewModel.cs"里面继承一个非常重要的"BindbleBase"(prism框架里面非常重要的)。所以…

《C++初阶之入门基础》【C++的前世今生】

【C的前世今生】目录 前言&#xff1a;---------------起源---------------一、历史背景二、横空出世---------------发展---------------三、标准立世C98&#xff1a;首个国际标准版本C03&#xff1a;小修订版本 四、现代进化C11&#xff1a;现代C的开端C14&#xff1a;对C11的…

YOLOv5-入门篇笔记

1.创建环境 conda create -n yolvo5 python3.8 去pytorch.org下载1.8.2的版本。 pip --default-timeout1688 install torch1.8.2 torchvision0.9.2 torchaudio0.8.2 --extra-index-url https://download.pytorch.org/whl/lts/1.8/cu111 github上下载yolov5的zip pip --def…

【PostgreSQL 03】PostGIS空间数据深度实战:从地图服务到智慧城市

PostGIS空间数据深度实战&#xff1a;从地图服务到智慧城市 关键词 PostGIS, 空间数据库, 地理信息系统, GIS, 空间查询, 地理分析, 位置服务, 智慧城市, 空间索引, 坐标系统 摘要 PostGIS是PostgreSQL的空间数据扩展&#xff0c;它将普通的关系数据库转变为强大的地理信息系统…