跳到主要内容

proto文件语法及工具命令

.proto 文件语法详解

.proto 文件是用来定义数据结构的协议文件,包含消息类型、字段及其数据类型等信息。以下是 .proto 文件的基本语法和规则:


1. 基本语法

  • syntax:指定使用的 Protobuf 版本,目前常用 proto3
  • package:指定包名,用于生成代码时的命名空间。
  • message:定义数据结构的关键字。
  • 字段定义:每个字段需要指定类型、名称和唯一编号。
  • 注释:支持 // 单行注释和 /* */ 多行注释。

2. 数据类型

类型描述说明
int3232位整数适用于较小范围的整数
int6464位整数适用于较大范围的整数
uint32无符号32位整数适用于非负整数
uint64无符号64位整数适用于非负整数
sint32压缩的有符号32位整数适用于包含正负值的整数
sint64压缩的有符号64位整数适用于包含正负值的整数
bool布尔值truefalse
string字符串必须是UTF-8编码的文本
bytes二进制数据用于存储任意字节数据
float32位浮点数浮点数类型
double64位浮点数双精度浮点数类型
enum枚举类型定义一组命名值

3. 字段规则

规则描述示例
optional字段是可选的(proto3 中已废弃)optional int32 age = 1;
repeated字段可以重复多次(相当于数组或列表)repeated string phone_numbers = 3;
required字段是必须的(proto3 中已废弃)required string name = 2;

4. 示例 .proto 文件

以下是一个完整的 .proto 文件示例,展示了各种语法的使用:

  syntax = "proto3"; // 指定 Protobuf 版本

// 定义包名
package tutorial;

// 定义一个简单的枚举类型
enum PhoneType {
MOBILE = 0; // 默认值
HOME = 1;
WORK = 2;
}

// 定义一个消息类型
message PhoneNumber {
string number = 1; // 电话号码
PhoneType type = 2; // 电话类型,使用上面定义的枚举
}

// 定义另一个消息类型
message Person {
int32 id = 1; // 用户 ID
string name = 2; // 用户名
string email = 3; // 邮箱
repeated PhoneNumber phones = 4; // 重复字段,表示多个电话号码
}

// 定义一个服务
service AddressBookService {
rpc AddPerson (Person) returns (Response);
rpc GetPerson (Request) returns (Person);
}

// 定义请求消息类型
message Request {
int32 id = 1; // 用户 ID
}

// 定义响应消息类型
message Response {
bool success = 1; // 操作是否成功
}

Protobuf 工具使用命令

1. 安装 Protobuf 编译器

  • Linux
    sudo apt update
    sudo apt install -y protobuf-compiler
  • macOS
    brew install protobuf
  • Windows
    1. 下载 Protobuf 的 预编译二进制文件
    2. 解压后将 protoc 可执行文件路径添加到环境变量中。

2. 基本编译命令

protoc --proto_path=路径 --<语言>_out=输出目录 文件名.proto
  • --proto_path:指定 .proto 文件所在的路径。
  • --<语言>_out:指定生成代码的目标语言和输出目录。

例如:

# 生成 Python 代码
protoc --proto_path=./ --python_out=./generated person.proto

# 生成 Go 代码
protoc --proto_path=./ --go_out=./generated person.proto

# 生成 Java 代码
protoc --proto_path=./ --java_out=./generated person.proto

3. 常用选项

参数作用
--proto_path=<路径>指定 .proto 文件的路径,默认为当前目录
--<语言>_out=<路径>指定生成的代码文件输出目录
--descriptor_set_out生成描述符文件,通常用于调试或动态加载
--include_imports将导入的 .proto 文件内容包含在描述符文件中
--include_source_info在描述符文件中包含源代码信息

4. 插件支持

Protobuf 支持通过插件扩展生成代码。以下是一些常见的插件:

  • Goprotoc-gen-go
    go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
    protoc --go_out=. --go_opt=paths=source_relative person.proto
  • gRPCprotoc-gen-grpc-java(Java 的 gRPC 插件)
    protoc --plugin=protoc-gen-grpc-java --grpc-java_out=./ person.proto

5. 验证安装

验证 protoc 是否安装成功:

protoc --version

输出类似以下内容表示安装成功:

libprotoc 3.x.x

Protobuf 的兼容性规则

  1. 添加字段:可以在不影响旧代码的情况下添加新字段。
  2. 删除字段:不能直接删除字段,可以标记为废弃(reserved)。
  3. 字段编号:不能更改已有字段的编号,否则会导致数据解析错误。
  4. 字段类型:不能更改现有字段的类型。

示例:

message Example {
int32 id = 1; // 不要更改编号
reserved 2, 3; // 标记字段编号 2 和 3 为废弃
reserved "old_field"; // 标记字段名 "old_field" 为废弃
}

总结

  • Protobuf 是一种高效的序列化工具,适用于跨语言、跨平台的场景。
  • 使用 .proto 文件定义数据结构,配合 protoc 工具生成代码。
  • 支持多种语言和扩展,灵活性强。
  • 遵循兼容性规则,确保数据格式的稳定性。