4.7.1 Protobuf扩展语法
目前Protobuf相关的很多开源项目都使用到了Protobuf的扩展语法。在前一节中提到的验证器就是通过给结构体成员增加扩展元信息实现验证。在grpc-gateway项目中,则是通过为服务的每个方法增加Http相关的映射规则实现对Rest接口的支持。pbgo也是通过Protobuf的扩展语法来为rest接口增加元信息。
pbgo的扩展语法在github.com/chai2010/pbgo/pbgo.proto文件定义:
syntax = "proto3";
package pbgo;
option go_package = "github.com/chai2010/pbgo;pbgo";
import "google/protobuf/descriptor.proto";
extend google.protobuf.MethodOptions {
HttpRule rest_api = 20180715;
}
message HttpRule {
string get = 1;
string put = 2;
string post = 3;
string delete = 4;
string patch = 5;
}pbgo.proto文件是pbgo框架的一个部分,需要被其他的proto文件导入。Protobuf本身自有一套完整的包体系,在这里包的路径就是pbgo。Go语言也有自己的一套包体系,我们需要通过go_package的扩展语法定义Protobuf和Go语言之间包的映射关系。定义Protobuf和Go语言之间包的映射关系之后,其他导入pbgo.ptoto包的Protobuf文件在生成Go语言时,会生成pbgo.proto映射的Go语言包路径。
Protobuf扩展语法有五种类型,分别是针对文件的扩展信息、针对message的扩展信息、针对message成员的扩展信息、针对service的扩展信息和针对service方法的扩展信息。在使用扩展前首先需要通过extend关键字定义扩展的类型和可以用于扩展的成员。扩展成员可以是基础类型,也可以是一个结构体类型。pbgo中只定义了service的方法的扩展,只定义了一个名为rest_api的扩展成员,类型是HttpRule结构体。
定义好扩展之后,我们就可以从其他的Protobuf文件中使用pbgo的扩展。创建一个hello.proto文件:
syntax = "proto3";
package hello_pb;
import "github.com/chai2010/pbgo/pbgo.proto";
message String {
string value = 1;
}
service HelloService {
rpc Hello (String) returns (String) {
option (pbgo.rest_api) = {
get: "/hello/:value"
};
}
}首先我们通过导入github.com/chai2010/pbgo/pbgo.proto文件引入扩展定义,然后在HelloService的Hello方法中使用了pbgo定义的扩展。Hello方法扩展的信息表示该方法对应一个REST接口,只有一个GET方法对应"/hello/:value"路径。在REST方法的路径中采用了httprouter路由包的语法规则,":value"表示路径中的该字段对应的是参数中同名的成员。
学员评价