Protocol Buffers (Proto) 语法详解
Protocol Buffers(简称Proto)是一种由Google开发的接口描述语言,用于数据结构的序列化,是一种跨语言的服务描述语言。它主要用于数据序列化,也支持定义服务接口。Proto文件定义了数据结构和RPC服务,然后可以生成各种语言的代码,以实现数据的序列化和反序列化,以及服务的调用。
1. Proto文件基础
1.1 语法版本
代码语言:c复制syntax = "proto3"; // 或者 "proto2"
syntax
指定使用的Proto语法版本,通常为proto3
或proto2
。
1.2 包名
代码语言:c复制package example;
package
定义了生成代码的包名,通常与文件名相关。
1.3 导入其他Proto文件
代码语言:c复制import "other.proto";
import
允许在当前Proto文件中使用其他Proto文件定义的消息类型。
1.4 go_package
选项
在 Protocol Buffers 的 .proto
文件中,go_package
选项用于指定生成的 Go 代码的包名和导入路径。这对于组织生成的代码和确保代码的一致性非常有用。
option go_package = "path/to/package";
go_package
是一个选项,可以设置为生成 Go 代码的包路径。
2. 定义数据结构
2.1 定义消息(Message)
代码语言:c复制message Person {
string name = 1;
int32 id = 2;
string email = 3;
}
message
关键字用于定义消息类型。- 每个字段有一个唯一标签(从1开始的整数),用于序列化时标识字段。
- 字段类型可以是基本数据类型、枚举、消息或其他复杂类型。
2.2 定义字段类型
Proto支持多种字段类型,包括:
double
、float
:双精度和单精度浮点数。int32
、int64
、sint32
、sint64
、fixed32
、fixed64
、sfixed32
、sfixed64
:整数类型。bool
:布尔类型。string
:字符串类型。bytes
:字节数组。enum
:枚举类型。message
:其他消息类型。
2.3 定义枚举(Enum)
代码语言:c复制enum Gender {
MALE = 0;
FEMALE = 1;
OTHER = 2;
}
enum
关键字用于定义枚举类型。- 枚举值从0开始,且每个值必须唯一。
2.4 定义字段规则
代码语言:c复制message Person {
string name = 1;
optional int32 id = 2; // 可选字段
repeated string emails = 3; // 可重复字段
}
optional
:字段可以不赋值。repeated
:字段可以重复出现,形成数组。
2.5 定义映射(Map)
代码语言:c复制map<string, int32> attributes = 1;
map
关键字用于定义映射类型。
2.6 定义一元类型(Oneof)
代码语言:c复制message Person {
oneof contact {
string email = 1;
string phone = 2;
}
}
oneof
关键字用于定义一个字段组,其中只有一个字段会被赋值。
3. 定义服务和RPC
3.1 定义服务(Service)
代码语言:c复制service PersonService {
rpc GetPerson(PersonRequest) returns (Person) {
option (google.api.http) = {
get: "/v1/people/{id}"
};
}
}
service
关键字用于定义服务。rpc
关键字定义远程过程调用(RPC)。returns
指定RPC调用的返回类型。
3.2 定义HTTP映射(HTTP Mapping)
代码语言:c复制option (google.api.http) = {
post: "/v1/people"
body: "*"
};
option (google.api.http)
用于定义HTTP映射,支持RESTful API风格,这一部分也可以不写。
4. Proto3特性
- 默认值:在Proto3中,所有字段默认为
optional
,无需显式声明。 - 无
required
字段:Proto3不支持required
字段。 - 无默认值:字段不能有默认值。
5. 实践示例
代码语言:c复制syntax = "proto3";
package example;
option go_package = "trpc-mysql-demo/service/user";
import "google/api/annotations.proto";
message Person {
string name = 1;
int32 id = 2;
string email = 3;
Gender gender = 4;
repeated string phone_numbers = 5;
map<string, int32> attributes = 6;
}
enum Gender {
MALE = 0;
FEMALE = 1;
OTHER = 2;
}
service PersonService {
rpc GetPerson(PersonRequest) returns (Person) {
option (google.api.http) = {
get: "/v1/people/{id}"
};
}
rpc CreatePerson(Person) returns (Person) {
option (google.api.http) = {
post: "/v1/people"
body: "*"
};
}
}
message PersonRequest {
int32 id = 1;
}
message PersonResponse {
Person person = 1;
}
- Person:定义一个包含姓名、ID、电子邮件、性别和电话号码的
Person
消息。 - PersonService:定义一个服务,包含获取个人信息和创建个人信息的RPC。
- PersonRequest 和 PersonResponse:定义RPC请求和响应的消息类型。
- HTTP映射:为
GetPerson
和CreatePerson
方法定义了HTTP映射,支持RESTful API风格。