目录
1.Protobuf
Protobuf 的特点
工作原理
Protobuf 与 JSON、XML 的对比
2.protobuf语法
1.数据类型
2.消息
3.枚举
4.嵌套消息
5.重复字段
6.默认值
7.其他类型
1.oneof类型
2.any类型
8.文件组织
3.protobuf命令
1.常见命令
选项:
1. --proto_path 或 -I
2. --cpp_out
1.Protobuf
Protocol Buffers(简称 Protobuf)是由 Google 开发的一种语言中立、平台中立、可扩展的序列化结构数据格式。它通常用于数据存储、网络通信等场景。Protobuf 可以在不同的语言(如 C++、Java、Python 等)之间高效地交换数据。
Protobuf 的特点
- 高效的二进制格式:Protobuf 使用紧凑的二进制格式进行数据序列化,相比于 XML 或 JSON 等文本格式,数据量更小、传输更快。
- 跨语言支持:Protobuf 支持多种编程语言,如 C++、Java、Python、Go、Ruby、C# 等,可以在不同语言的应用程序之间进行数据交换。
- 易于扩展:Protobuf 提供了版本控制机制,可以在不破坏已有数据结构的情况下进行向后兼容的扩展。
- 简单易用的定义:通过一种专用的 IDL(接口定义语言)定义数据结构,使得数据序列化和反序列化过程变得简单。
工作原理
- 定义数据结构:你首先用一种类似于结构体的方式,使用 Protobuf 的
.proto
文件来定义数据结构。 - 编译:然后使用 Protobuf 提供的编译器(
protoc
)将.proto
文件编译成目标语言的源代码。 - 序列化和反序列化:生成的代码包含序列化(将对象转换为字节流)和反序列化(将字节流恢复为对象)的逻辑。
Protobuf 与 JSON、XML 的对比
特性 | protobuf | json | xml |
数据格式 | 二进制 | 文本格式 | 文本格式 |
可读性 | 不可读 | 可读 | 可读 |
数据大小 | 非常紧凑,较小 | 较大 | 较大 |
性能 | 非常快 | 较慢 | 较慢 |
支持的语言 | 多种语言支持 | 多种语言支持 | 多种语言支持 |
扩展性 | 强 | 较弱 | 较弱 |
2.protobuf语法
protobuf在使用时需要指定语法版本:
syntax = "proto3"; // 指定 Protobuf 语法版本
1.数据类型
protobuf支持多种数据类型,具体如下:
int32
,int64
: 有符号整数(32位/64位)uint32
,uint64
: 无符号整数(32位/64位)sint32
,sint64
: 有符号整数,采用 ZigZag 编码来提高编码效率fixed32
,fixed64
: 无符号整数,固定大小,性能更好sfixed32
,sfixed64
: 有符号整数,固定大小float
,double
: 浮动精度(32位/64位)bool
: 布尔值(true
或false
)string
: 字符串(UTF-8 编码)bytes
: 原始字节数据
message Example {int32 id = 1;string name = 2;float value = 3;
}
2.消息
Protobuf 的核心是 Message(消息),它是数据结构的基础单位。消息由字段(fields)组成,每个字段都有类型、名称和唯一的字段编号。
message Person {string name = 1; // 字段名称和编号int32 id = 2;string email = 3;
}
- 每一个字段都有一个字段编号,他是唯一的,按顺序分配
- 字段编号是正整数,不能修改
3.枚举
Protobuf 还支持枚举类型,适用于定义一组常量。
enum Status {ACTIVE = 0; // 默认值INACTIVE = 1;PENDING = 2;
}message Person {string name = 1;Status status = 2; // 使用枚举类型
}
4.嵌套消息
消息可以嵌套其他消息,也可以定义重复字段。
message Address {string street = 1;string city = 2;string postal_code = 3;
}message Person {string name = 1;Address address = 2; // 嵌套消息
}
5.重复字段
repeated修饰符用于定义数组或列表字段,可以存储多个值。
message Person {string name = 1;repeated string phone_numbers = 2; // 可以存储多个电话号码
}
6.默认值
在 proto3 中,所有字段有默认值,string
类型默认为空字符串,int32
默认为 0,bool
默认为 false
,enum
类型默认为第一个枚举值。
7.其他类型
1.oneof类型
oneof
用于在消息中定义互斥字段,只有一个字段可以有值。
message Person {oneof contact {string email = 1;string phone = 2;}
}
2.any类型
Protobuf 允许定义动态类型字段,称为 Any
类型,表示可以存储任何类型的数据。
import "google/protobuf/any.proto";message Container {google.protobuf.Any item = 1;
}
8.文件组织
通常会将不同的消息和服务定义放在多个 .proto
文件中,并通过 import
来引用。
import "address.proto"; // 引入外部的 proto 文件message Person {string name = 1;Address address = 2; // 使用外部定义的 Address 类型
}
3.protobuf命令
1.常见命令
protoc
是 Protobuf 提供的编译器,用于将 .proto
文件编译为不同语言的源代码。
protoc [OPTION] PROTO_FILES
选项:
1. --proto_path
或 -I
--proto_path
用于指定 .proto
文件的搜索路径。当你的 .proto
文件引用了其他 .proto
文件时,必须指定该选项。
protoc -I=src --python_out=out src/person.proto
2. --cpp_out
此选项用于指定输出的 C++ 代码目录。Protobuf 会根据 .proto
文件生成相应的 C++ 类。
protoc --cpp_out=./generated person.proto
注:其他语法用法相同