protobuf学习1
- 参考文章:ProtoBuf详解_proto buf-CSDN博客
- 参考文章:Protocol Buffer 编译器安装 | Protocol Buffers 文档 - ProtoBuf 文档
- 参考博客:【ProtoBuf】在 Windows / Linux 安装 ProtoBuf 编译器(超详细教程)-CSDN博客
基础知识
protobuf英文全称为Protocol Buffers,是Google的一种语言中立、平台中立、可扩展的结构化数据序列化机制。它类似于 JSON,但更小更快,并且能生成原生语言绑定。你只需一次性定义好你想要的数据结构,然后就可以使用专门生成的源代码,轻松地从各种数据流中读写你的结构化数据,并支持多种语言。
序列化和反序列化
-
序列化和反序列化对于学web的可能比较熟悉,但我不是学web的,所以简单介绍一下:
-
序列化:就是将一个对象转换为字节序的过程;
-
反序列化:就是将一个字节序转换为一个完整对象的过程;
-
使用序列化的情况:
- 存储数据:当你想把的内存中的对象状态保存到⼀个⽂件中或者存到数据库中时。
- 网络传输:网络直接传输数据,但是无法直接传输对象,所以要在传输前序列化,传输完成后反 序列化成对象。例如我们之前学习过socket编程中发送与接收数据。
-
主流的序列化和反序列化工具有:XML、JSON、ProtoBuf;
-
protobuf版本
- 目前
protobuf的大版本只有protobuf2、protobuf3,这两个大版本。protobuf是开源的,其源代码和发行版都被放置在github仓库中,对应的网址:protocolbuffers/protobuf: Protocol Buffers - Google’s data interchange format - 通过翻找github上protobuf的发行版,会发现protobuf的版本号有
V x.y.z以及下图所示的V x.y这种。- 其中
V x.y.z,x表示主版本号,y表示次版本号,z表示补丁版本号。而通过翻阅后面会发现主版本号只出现2、3 - 由于主版本号只出现
2、3,所以更新到后面主版本号意义确实不太大了,所以就更换了版本号的命名方案,将版本号3给省略了,变成x.y的形式。这种形式默认是protobuf3。(图中V 21.0其实就是这种形式) - 通过观察github仓库的版本,protobuf2的版本范围为:
v2.4.1到v2.6.1,而protobuf3的版本范围为:v3.0.0到v3.20.1。而版本命名后的目前截止至2025年10月11日,protobuf的版本已经是从v21.0到v33.0
- 其中
- 为了能用上新版本的一些功能以及向下兼容,所以在安装
protobuf的时候最好还是安装最新版本,protobuf3是兼容protobuf2的。

protobuf工作原理
使用步骤如下:
- 编写.proto⽂件,⽬的是为了定义结构对象(message)及属性内容。
- 使⽤ protoc 编译器编译 .proto ⽂件,⽣成⼀系列接口代码,存放在新⽣成头⽂件和源⽂件中。
- 依赖⽣成的接口。将编译⽣成的头⽂件包含进我们的代码中,使用编译器为我们生成的序列化,反序列化方法以及一些对消息字段进行读写的方法。

protobuf环境搭建
所谓搭建protobuf环境,其实就是安装protoc编译器,以及Python相关的库,这样基本就可以在C语言中以及Python中使用protobuf结构体。
- 下载ProtoBuf前一定要安装依赖库:
autoconf automake libtool curl make g++ unzip,否则安装会出现问题。安装命令如下:
1 | sudo apt-get install autoconf automake libtool curl make g++ unzip -y |
- 然后去到
protobuf的github网站上的releases的网站上选择该选项并复制链接,这个博客的安装方法是24年12月份安装的,所以版本还没到v30甚至以上。Releases · protocolbuffers/protobuf

- 然后在Linux下使用命令
wget下载对应连接的压缩包,并且将压缩包解压出来。
1 | wget https://github.com/protocolbuffers/protobuf/releases/download/v29.1/protoc-29.1-linux-x86_64.zip |

- 先创建一个
protoc-29.1-linux-x86_64文件夹用来存放,解压后的protbuf文件。
1 | mkdir protoc-29.1-linux-x86_64 |
- 之后对下载下来的压缩包进行解压,解压到指定文件,使用如下命令
1 | unzip ./protoc-29.1-linux-x86_64.zip -d ./protoc-29.1-linux-x86_64 |
- 然后进入该文件夹,将
bin/protoc可执行文件和include/google目录分别放到usr/local/bin和usr/local/include目录下
1 | sudo cp ./protoc /usr/local/bin/ |
- 移动完之后执行
protoc --version就会出现如下信息,这就代表着protoc成功安装完成了。

protobuf编译
- 给出如下的
protobuf代码,看看如何编译它,编译它后什么文件会输出出来,先不用理解代码中的内容。创建一个.proto文件。
1 | syntax = "proto3"; |

- 接下来使用
protoc --python_out=. protobuf1.proto,将该protobuf1文件给编译一下,发现编译后出现了一个.py文件。

1 | # -*- coding: utf-8 -*- |
- 还可以编译成
.C文件,以及.CPP文件,使用protoc --c_out=. protobuf1.proto将生成.c文件和.h文件。然后使用protoc --cpp_out=. protobuf1.proto就可以生成.cc文件和.h文件。


| 编译指令 | 结果 |
|---|---|
protoc --c_out=. protobuf1.proto |
生成.c文件以及.h文件 |
protoc --python_out=. protobuf1.proto |
生成.py文件 |
protoc --cpp_out=. protobuf1.proto |
生成.cc文件以及.h文件 |
protobuf使用
- 现在已经将
protobuf进行编译,编译成了其他语言的文件,那如何在编写其他语言的情况下使用这个protobuf文件。接下来的例子就是做一个实例了解一下如何使用。
1 | # 注意如果第一次编写的时候应该需要下载protobuf1_pb2.py文件所包含的库文件 |

数据类型
标量类型
Protobuf支持多种标量类型,具体如下表:
| 数据类型 | 说明 | 示例 |
|---|---|---|
int32、int64 |
32位或64位有符号整数 | int age=1; |
uint32、uint64 |
32位或64位无符号整数 | uint32 id=2; |
float |
单精度浮点数 | float score = 3; |
double |
双精度浮点数 | double ratio = 4; |
bool |
布尔值 | bool is_active = 5; |
string |
字符串 | string name=6; |
bytes |
二进制数据 | bytes data=7; |
复合类型
- 枚举类型:用于定义一组命名常量。使用关键字
enum进行定义。 - 消息类型:类似于结构体,用于定义复杂的数据结构。使用
message关键字进行定义。
例子1:
1 | // 下面创建一个包含枚举类型的消息 |
例子2:
1 | syntax = "proto3"; |
基本语法
语法版本
使用syntax指定protobuf的版本(proto2或proto3),目前推荐使用proto3。例子如下:
1 | syntax = "proto3"; // 使用protobuf3的版本 |
包声明
使用package定义命名空间,避免不同模块间的命名冲突。例子如下:
1 | package my_package; |
导入其他文件
使用import 导入其他的.proto文件中的定义。例子如下:
1 | import "common.proto"; |
注释
对于protobuf的注释和C语言是一样的,都是通过// 进行单行注释。以及通过/**/进行多行注释。
1 | // 这是protobuf的单行注释 |
定义与声明数据
对于proto3,可以使用数据类型 变量名 = 字段编号来定义和声明数据类型。例子如下:
1 | syntax = "proto3"; |
注意:字段编号是字段编号,而不是这些变量的默认值,在protbuf中会自动给变量赋予一个默认值。各种类型的默认值如下:
| 字段类型 | 默认值 |
|---|---|
数值类型int32 uint32等 |
0 |
| 字符串 | ""(空字符串) |
| bool | false |
| 枚举 | 枚举中值为0的项 |
| message | nil/None(未设置) |
对于proto2来说,可以使用标记词 变量名 = 字段编号;来定义和声明数据类型。例子如下:
1 | syntax = "proto2"; |
标记词
- 标记词在
proto2中定义变量是必须要修饰的,而proto3在定义变量的时候默认使用optional修饰,不必要求用户显式的定义声明。接下来介绍一下这些标记词。
| 标记词 | 含义 | 说明 |
|---|---|---|
required(proto3已经被移除) |
必须字段 | 必须赋值,如果不赋值序列化会失败,反序列化可能也会出错 |
optional |
可选字段 | 可以设置;不设置时会使用默认值 |
repeated |
可重复字段 | 类似数组或列表,可出现多次 |
- 对于
repeated字段,表示重复字段,可以出现多次,等价于数组或者列表
1 | message Student { |
proto3语法详解
消息——基本结构
- 消息,也就是类似于C语言结构体的东西,是
protobuf的核心,用于定义数据结构。
1 | syntax = "proto3"; |
嵌套消息
- 一个消息结构中可以嵌套另一个消息结构。
1 | syntax = "proto3"; |
枚举类型
1 | syntax = "proto3"; |
服务定义
- 用于定义
RPC服务的接口。
1 | service UserSerice { |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 iyheart的博客!

