Protocol Buffers 使用了一种中立、平台无关的语言来定义数据结构,使得不同编程语言、不同平台之间能够进行数据交互。Protocol Buffers 目前主要有 Proto2 和 Proto3 两个版本,Proto3 保持了与 Proto2 的一定程度的兼容性。但是,某些 Proto2 特性在 Proto3 中不再支持。
- 标量类型 {#title-0} ==================
在 Protobuf 中,标量类型 (Scalar Types)是指一些基本的数据类型,可以直接在 .proto
文件中定义并用于数据字段。这些类型对应于原生的简单数据类型,类似于编程语言中的整型、浮点型、布尔型等。
Document:https://protobuf.dev/programming-guides/proto3/#scalar
案例:在 protos 目录中创建 employee.proto 文件,定义 Employee 消息:
syntax = "proto3";
message Employee
{
// 姓名
string name = 1;
// 年龄
int32 age = 2;
// 薪资
double salary = 3;
// 性别
bool gender = 4;
}
**注意:**当创建数据字段时,每个字段都需要指定一个唯一的位置编号,用于区分不同的字段。
最后使用 protoc 编译器生成对应语言的操作代码:
protoc protos/employee.proto --python_out=output
protoc protos/employee.proto --cpp_out=output
- 复杂类型 {#title-1} ==================
在 message 中也可以定义较为复杂的类型,例如:
- 枚举类型:枚举类型用于定义一组命名常量
- 嵌套消息:在一个消息中嵌套另一个消息
- 重复字段:表示一个字段可以出现零次或多次,可以理解为动态数组
- 映射字段:表示键值对的集合
案例:在 protos 目录中创建 developer.proto 文件,定义 Developer 消息:
syntax = "proto3";
message Other
{
int32 v1 = 1;
int32 v2 = 2;
}
enum Week
{
// 第一个枚举项的值必须为 0,在 proto2 中没有此限制,这是因为对于枚举类型默认值是 0
// 后续的枚举项值可以是任意的、不重复的
Mon = 0;
Tue = 3;
Wed = 4;
Thu = 5;
Fri = 6;
Sat = 7;
Sun = 8;
}
message Developer
{
string name = 1;
Week week = 2;
repeated int32 list = 3;
map<string, int32> map = 4;
Other oher = 5;
}
执行如下命令生成对应语言的操作代码:
protoc protos/developer.proto --cpp_out=output
**注意:message 允许嵌套定义,即:message 中嵌套另外一个 message。**在 protos 目录中创建 nested.proto 文件,定义 Developer 消息:
syntax = "proto3";
message Nested
{
string name = 1;
map<string, int32> teles = 2;
message Other
{
int32 v1 = 1;
int32 v2 = 2;
}
Other other = 3;
}
protoc protos/nested.proto --cpp_out=output
- import 用法 {#title-2} =======================
import
指令允许在 Protobuf 中将一个 .proto 文件中的定义引入到另一个 .proto 文件中,以便在后者中使用前者中定义的消息类型、枚举类型等。
这种组织方式有助于管理大型的 .proto 定义,使得可以将不同的消息类型分别定义在不同的文件中,并通过 import
将它们组合在一起。import
指令通常位于文件顶部,其语法类似于其他编程语言中的导入或引用语句。
案例:在 protos 目录中创建 specialist.proto 文件,定义 Specialist 消息:
syntax = "proto3";
// 导入 employee.proto 文件
import "protos/employee.proto";
message Specialist
{
string name = 1;
int32 age = 2;
// 使用其他 employee.proto 定义的数据类型
Employee emp = 3;
}
执行如下命令生成对应语言的操作代码:
protoc protos/specialist.proto --cpp_out=output
- package 用法 {#title-3} ========================
在 Protobuf 中,package
关键字用于定义一个命名空间,用于组织和管理定义的消息类型。它有助于避免命名冲突,并使得代码更加清晰和易于维护。
在 protos 目录中创建 common1.proto 文件,在 foo.bar1 中定义 Information 消息:
syntax = "proto3";
package foo.bar1;
message Information
{
string info_content1 = 1;
string info_content2 = 2;
}
在 protos 目录中创建 common2.proto 文件,在 foo.bar2 中定义 Information 消息:
syntax = "proto3";
package foo.bar2;
message Information
{
int32 info_id1 = 1;
int32 info_id2 = 2;
}
在 protos 目录中创建 common.proto 文件,定义 Message 消息:
syntax = "proto3";
import "protos/common1.proto";
import "protos/common2.proto";
message Message
{
// 通过包名访问 Message 类型
foo.bar1.Information info1 = 1;
foo.bar2.Information info2 = 2;
}
protoc protos/common.proto --cpp_out=output