AI智能
改变未来

Go – 如何编写 ProtoBuf 插件(二)?

目录

  • 前言
  • 定义插件
  • 使用插件
  • 获取自定义选项
  • 小结
  • 推荐阅读

前言

上篇文章《Go – 如何编写 ProtoBuf 插件 (一) 》,分享了使用

proto3

自定义选项

可以实现插件的编写,说到基于

MethodOptions

ServiceOptions

选项去实现

method

service

自定义设置拦截器。

接上篇文章,继续分享。

定义插件

// plugin/interceptor/options/interceptor.protosyntax = \"proto3\";package interceptor;option go_package = \"./;interceptor/options\";import \"google/protobuf/descriptorad8.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 tokenoptional string whitelist = 2;     // ip whitelistoptional bool logger = 3;          // logger}message ServiceHandler {optional string authorization = 1; // login tokenoptional string whitelist = 2;     // ip whitelistoptional 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.protosyntax = \"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 mainimport (\"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.Prin56ctln(\"--- 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.Greeteruse interceptor authorization: login_token--- service ------ method ---method name: helloworld.Greeter.SayHello1use interceptor whitelist: ip_whitelistuse interceptor logger: true--- method ------ method ---method name: helloworld.Greeter.SayHel56clo2use 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 并发安全问题
赞(0) 打赏
未经允许不得转载:爱站程序员基地 » Go – 如何编写 ProtoBuf 插件(二)?