共计 3697 个字符,预计需要花费 10 分钟才能阅读完成。
前言
上篇文章《Go – 如何编写 ProtoBuf 插件 (一)》,分享了应用 proto3
的 自定义选项
能够实现插件的编写,说到基于 MethodOptions
和 ServiceOptions
选项去实现 method
和 service
自定义设置拦截器。
接上篇文章,持续分享。
定义插件
// plugin/interceptor/options/interceptor.proto
syntax = "proto3";
package interceptor;
option go_package = "./;interceptor/options";
import "google/protobuf/descriptor.proto";
extend google.protobuf.MethodOptions {optional MethodHandler method_handler = 63500;}
extend google.protobuf.ServiceOptions {optional ServiceHandler service_handler = 63501;}
message MethodHandler {
optional string authorization = 1; // login token
optional string whitelist = 2; // ip whitelist
optional bool logger = 3; // logger
}
message ServiceHandler {
optional string authorization = 1; // login token
optional string whitelist = 2; // ip whitelist
optional bool logger = 3; // logger
}
接下来依据 interceptor.proto
生成 interceptor.pb.go
// 生成 interceptor.pb.go
// 应用的 protoc --version 为 libprotoc 3.18.1
// 应用的 protoc-gen-go --version 为 protoc-gen-go v1.27.1
// 在 plugin/interceptor/options 目录下执行 protoc 命令
protoc --go_out=. interceptor.proto
应用插件
// helloworld/helloworld.proto
syntax = "proto3";
package helloworld;
option go_package = "./;helloworld";
import "plugin/interceptor/options/interceptor.proto";
service Greeter {option (interceptor.service_handler) = {authorization : "login_token",};
rpc SayHello1 (HelloRequest) returns (HelloReply) {option (interceptor.method_handler) = {
whitelist : "ip_whitelist",
logger: true,
};
}
rpc SayHello2 (HelloRequest) returns (HelloReply) {option (interceptor.method_handler) = {logger: false,};
}
}
message HelloRequest {string name = 1;}
message HelloReply {string message = 1;}
接下来依据 helloworld.proto
生成 helloworld.pb.go
// 生成 helloworld.pb.go
// 应用的 protoc --version 为 libprotoc 3.18.1
// 应用的 protoc-gen-go --version 为 protoc-gen-go v1.27.1
// 在根目录下执行 protoc 命令
protoc --go_out=helloworld/gen helloworld/helloworld.proto
获取自定义选项
// main.go
// 演示代码
package main
import (
"fmt"
"strconv"
_ "github.com/xinliangnote/protobuf/helloworld/gen"
"github.com/xinliangnote/protobuf/plugin/interceptor/options"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
)
func main() {protoregistry.GlobalFiles.RangeFiles(func(fd protoreflect.FileDescriptor) bool {services := fd.Services()
for i := 0; i < services.Len(); i++ {service := services.Get(i)
if serviceHandler, _ := proto.GetExtension(service.Options(), options.E_ServiceHandler).(*options.ServiceHandler); serviceHandler != nil {fmt.Println()
fmt.Println("--- service ---")
fmt.Println("service name:" + string(service.FullName()))
if serviceHandler.Authorization != nil && *serviceHandler.Authorization != "" {fmt.Println("use interceptor authorization:" + *serviceHandler.Authorization)
}
fmt.Println("--- service ---")
}
methods := service.Methods()
for k := 0; k < methods.Len(); k++ {method := methods.Get(k)
if methodHandler, _ := proto.GetExtension(method.Options(), options.E_MethodHandler).(*options.MethodHandler); methodHandler != nil {fmt.Println()
fmt.Println("--- method ---")
fmt.Println("method name:" + string(method.FullName()))
if methodHandler.Whitelist != nil && *methodHandler.Whitelist != "" {fmt.Println("use interceptor whitelist:" + *methodHandler.Whitelist)
}
if methodHandler.Logger != nil {fmt.Println("use interceptor logger:" + strconv.FormatBool(*methodHandler.Logger))
}
fmt.Println("--- method ---")
}
}
}
return true
})
}
输入:
--- service ---
service name: helloworld.Greeter
use interceptor authorization: login_token
--- service ---
--- method ---
method name: helloworld.Greeter.SayHello1
use interceptor whitelist: ip_whitelist
use interceptor logger: true
--- method ---
--- method ---
method name: helloworld.Greeter.SayHello2
use interceptor logger: false
--- method ---
小结
本文次要内容是基于 自定义选项
定义了 interceptor
插件,而后在 helloworld.proto
中应用了插件,最初在 golang
代码中获取到应用的插件信息。
接下来,要对获取到的插件信息进行应用,次要用在 grpc.ServerOption
中,例如在 grpc.UnaryInterceptor
和 grpc.StreamInterceptor
中应用。
举荐浏览
- Go – 如何编写 ProtoBuf 插件 (一)?
- Go – 对于 protoc 工具的小纳闷
- Go – 对于 .proto 文件的小思考
- Go – 基于逃逸剖析来晋升程序性能
- Go – 应用 sync.Map 解决 map 并发平安问题
正文完