proto文件解读
syntax = "proto3"; //指定proto版本
package hello_proto; //指定默认包名
//指定golang包名
option go_package = "/hello_proto"; //在hello.proto文件所在的目录下生成一个名为hello_proto的目录存放.pb.go文件
//option go_package = ".;xxx"; 这样写,是在hello.proto文件所在的目录下直接生成.pb.go文件,文件的包名为xxx
//定义rpc服务
//service 对应的是go语言的接口interface
service HelloService {
//定义函数/方法
//rpc对应的是go结构体中的方法
rpc SayHello (HelloRequest) returns (HelloResponse) {}
}
//HelloRequest 请求内容
//message对应的是go的struct
message HelloRequest {
string name = 1;
string message = 2;
}
//HelloResponse 回应内容
message HelloResponse {
string name = 1;
string message = 2;
}
- 对比原始的
rpc
就会发现,proto
文件直接定义好了请求和接收体,不用在服务端和客户端程序去进行重复的编写。 - 而且 函数/方法 也是在
proto
里面就定义好了,能被编译器进行读取进行代码提示,编写代码难度和复杂度都降低了。 整体只用编写
proto
文件、客户端和服务端程序就行了,proto
文件对应的代码都是用cmd
自己生成的,一般不需要开发者关心。protoc -I . --go_out=plugins=grpc:./grpc/grpc_proto .\grpc\grpc_proto\hello.proto //在当前目录下的grpc目录里的grpc_proto目录生成grpc目录下的grpc_proto目录下的hello.proto文件的.proto文件
- 函数/方法 的请求体和返回体都说明好了,直观又易读。
- 重要的是
grpc
跨语言 !
其中,proto文件内有多个不同的service又叫多服务。例如:
syntax = "proto3";
option go_package = "/multservice_proto";
service VideoService {
rpc Watch (Request) returns (Response) {}
}
service OrderService {
rpc Buy (Request) returns (Response) {}
}
message Request {
string name = 1;
string message = 2;
}
message Response {
string name = 1;
string message = 2;
}
proto文件基本的数据类型
message Request {
double a1 = 1; float64
float a2 = 2; float32
int32 a3 = 3; int32
uint32 a4 = 4; uint32
uint64 a5 = 5; uint64
sint32 a6 = 6; int32
sint64 a7 = 7; int64
fixed32 a8 = 8; uint32
fixed64 a9 = 9; uint64
sfixed32 a10 = 10; int32
sfixed64 a11 = 11; int64
bool a12 = 12; bool
string a13 = 13; string
bytes a14 = 14; 对应[]byte
}
go对应类型
type Request struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
A1 float64 `protobuf:"fixed64,1,opt,name=a1,proto3" json:"a1,omitempty"`
A2 float32 `protobuf:"fixed32,2,opt,name=a2,proto3" json:"a2,omitempty"`
A3 int32 `protobuf:"varint,3,opt,name=a3,proto3" json:"a3,omitempty"`
A4 uint32 `protobuf:"varint,4,opt,name=a4,proto3" json:"a4,omitempty"`
A5 uint64 `protobuf:"varint,5,opt,name=a5,proto3" json:"a5,omitempty"`
A6 int32 `protobuf:"zigzag32,6,opt,name=a6,proto3" json:"a6,omitempty"`
A7 int64 `protobuf:"zigzag64,7,opt,name=a7,proto3" json:"a7,omitempty"`
A8 uint32 `protobuf:"fixed32,8,opt,name=a8,proto3" json:"a8,omitempty"`
A9 uint64 `protobuf:"fixed64,9,opt,name=a9,proto3" json:"a9,omitempty"`
A10 int32 `protobuf:"fixed32,10,opt,name=a10,proto3" json:"a10,omitempty"`
A11 int64 `protobuf:"fixed64,11,opt,name=a11,proto3" json:"a11,omitempty"`
A12 bool `protobuf:"varint,12,opt,name=a12,proto3" json:"a12,omitempty"`
A13 string `protobuf:"bytes,13,opt,name=a13,proto3" json:"a13,omitempty"`
A14 []byte `protobuf:"bytes,14,opt,name=a14,proto3" json:"a14,omitempty"`
}
数组类型
message Request {
string xxx = 1;
fixed32 code = 2;
}
message ArrayRequest {
repeated int64 a1 = 1;
repeated string a2 = 2;
repeated Request request_list = 3;
}
go对应类型
type ArrayRequest struct {
A1 []int64
A2 []string
RequestList []*Request
}
map类型
键(key)只能是基本类型
message MapRequest {
map<int64, string> m_i_s = 1;
map<string, bool> m_i_b = 2;
map<string, Request> m_i_arr = 3;
}
go对应类型
type MapRequest struct {
MIS map[int64]string
MIB map[string]bool
MIArr map[string]*ArrayRequest
}
嵌套类型
message Q1 {
message Q2{
string name2 = 2;
}
string name1 = 1;
Q2 q2 = 2;
}
与上同样,几乎没差别,明显的看出来下面这种写法更易读
message Q2 {
string name2 = 2;
}
message Q1 {
string name1 = 1;
Q2 q2 = 2;
}
对应go类型
type Q1 struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Name1 string `protobuf:"bytes,1,opt,name=name1,proto3" json:"name1,omitempty"`
Q2 *Q1_Q2 `protobuf:"bytes,2,opt,name=q2,proto3" json:"q2,omitempty"`
}
编写风格
- 文件名建议下划线,例如:
my_student.proto
- 包名和目录名对应
- 服务名、方法名、消息名均为大驼峰
- 字段名为下划线,小驼峰。但实际自己生成会将下划线去掉,然后将下划线之后的第一个字母大写。
评论(0)