您的位置:首页 > 编程语言 > Go语言

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

2021-12-18 15:26 966 查看

目录

前言

上篇文章《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
ad8
.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.Prin
56c
tln("--- 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.SayHel
56c
lo2
use interceptor logger: false
--- method ---

小结

本文主要内容是基于

自定义选项
定义了
interceptor
插件,然后在
helloworld.proto
中使用了插件,最后在
golang
代码中获取到使用的插件信息。

接下来,要对获取到的插件信息进行使用,主要用在

grpc.ServerOption
中,例如在
grpc.UnaryInterceptor
grpc.StreamInterceptor
中使用。

推荐阅读

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: