前言

上篇文章《Go - 如何编写 ProtoBuf 插件 (一) 》,分享了使用 proto3自定义选项 可以实现插件的编写,说到基于 MethodOptionsServiceOptions 选项去实现 methodservice 自定义设置拦截器。

接上篇文章,继续分享。

定义插件

// 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.UnaryInterceptorgrpc.StreamInterceptor 中使用。

推荐阅读

Go - 如何编写 ProtoBuf 插件(二)?的更多相关文章

  1. Go - 如何编写 ProtoBuf 插件 (三) ?

    目录 前言 演示代码 小结 推荐阅读 前言 上篇文章<Go - 如何编写 ProtoBuf 插件 (二) >,分享了基于 自定义选项 定义了 interceptor 插件,然后在 hell ...

  2. [翻译]如何编写GIMP插件(二)

    写在前面: 本人翻译并不专业,甚至英语不好,翻译内容仅供参考.由于博主是边学边翻译,所以不能保证翻译的准确性和正确性,如果可以,请查看原版学习,本文仅作学习记录之用. <How to write ...

  3. 编写jQuery插件--实现返回顶部插件

    国庆过去一周多了,作为IT界的具有严重’工作狂‘性质的宅人,居然还没走出玩耍的心情,拖了程序猿的脚后跟了.最近工作不顺,心情不佳,想吐槽下公司,想了还是厚道点,以彼之道还施彼身,觉得自己也和他们同流合 ...

  4. 使用Qt编写模块化插件式应用程序

    动态链接库技术使软件工程师们兽血沸腾,它使得应用系统(程序)可以以二进制模块的形式灵活地组建起来.比起源码级别的模块化,二进制级别的模块划分使得各模块更加独立,各模块可以分别编译和链接,模块的升级不会 ...

  5. [翻译]如何编写GIMP插件(一)

    近期想尝试编写gimp插件,在gimp官网看到了三篇简明教程,顺便翻译了下,由于本人英文,计算机知识有限,文中难免有warning,error出现,欢迎指正. <How to write a G ...

  6. Lua编写wireshark插件初探——解析Websocket上的MQTT协议

    一.背景 最近在做物联网流量分析时发现, App在使用MQTT协议时往往通过SSL+WebSocket+MQTT这种方式与服务器通信,在使用SSL中间人截获数据后,Wireshark不能自动解析出MQ ...

  7. 金蝶K3 wise 插件二次开发与配置

    金蝶K3 wise 插件二次开发与配置 开发环境:K/3 Wise 13.0.K/3 Bos开发平台.Visual Basic 6.0 目录 一.二次开发插件编程二.代码演示三.配置插件四.测试插件五 ...

  8. 前端html、CSS快速编写代码插件-Emmet使用方法技巧详解

    前端html.CSS快速编写代码插件-Emmet使用方法技巧详解   Emmet的前身是大名鼎鼎的Zen coding,如果你从事Web前端开发的话,对该插件一定不会陌生.它使用仿CSS选择器的语法来 ...

  9. Qt 显示透明flash和编写QtWebkit插件

    Qt 有两种方法可以显示flash. 1. 通过QAxWidget 调用com形式显示flash, 需要本机安装IE flash插件 2. 直接通过qwebview显示flash, 需要下载webki ...

随机推荐

  1. [hdu6973]Bookshop

    将询问拆成$x$​到$lca$​和$lca$​($lca$​靠近$y$​的儿子)到$y$​​两部分,分别处理(后者以前者的答案为基础) 两者是类似地,不妨仅考虑前者:用树剖将该询问拆成dfs序上若干个 ...

  2. python的异常打印

    在代码运行中有的代码可能会发生异常,但是奇怪的是异常信息并没有打印出来, 于是我们在代码中加入这个就能打印出来啦. try: #playsound(msg.file_name()) #playsoun ...

  3. 『与善仁』Appium基础 — 14、Appium测试环境搭建

    目录 1.Appium测试环境搭建整体思路 (1)Android测试环境搭建 (2)Appium测试环境搭建 (3)测试脚本语言的环境搭建 2.Appium在Android端和IOS端的工作流程 (1 ...

  4. NLP获取词向量的方法(Glove、n-gram、word2vec、fastText、ELMo 对比分析)

    自然语言处理的第一步就是获取词向量,获取词向量的方法总体可以分为两种两种,一个是基于统计方法的,一种是基于语言模型的. 1 Glove - 基于统计方法 Glove是一个典型的基于统计的获取词向量的方 ...

  5. bzoj4036 / P3175 [HAOI2015]按位或

    bzoj4036 / P3175 [HAOI2015]按位或 是一个 min-max容斥 的板子题. min-max容斥 式子: $ \displaystyle max(S) = \sum_{T\su ...

  6. Codeforces 685C - Optimal Point(分类讨论+乱搞)

    Codeforces 题面传送门 & 洛谷题面传送门 分类讨论神题. 首先看到最大值最小,一眼二分答案,于是问题转化为判定性问题,即是否 \(\exists x_0,y_0,z_0\) 满足 ...

  7. CF1202E You Are Given Some Strings...

    题目传送门. 题意简述:给出 \(t\) 与 \(s_{1,2,\cdots,n}\).求对于所有 \(i,j\in[1,n]\),\(s_i+s_j\) 在 \(t\) 中出现次数之和. 如果只有 ...

  8. P5599【XR-4】文本编辑器

    题目传送门. 题意简述:给定长度为 \(n\) 的文本串 \(a\) 和有 \(m\) 个单词的字典 \(s_i\).\(q\) 次操作,每次求出字典内所有单词在 \(a[l,r]\) 的出现次数,或 ...

  9. Perl语言编程(大骆驼)

    啰嗦几句 Perl的时代已经过去,现在年轻的同事们基本上都在用Python了.但个人认为单就生物信息文本处理而言,Perl语言是绝对够用的.最主要的是,前辈们搭建的流程大多数是Perl写的,因此,如果 ...

  10. 修改Ubuntu中locale转中文为英文

    修改Ubuntu 的命令行为英文版  编辑 /etc/default/locale 文件 原来的配置为: LANG="zh_CN.UTF-8″ LANGUAGE="zh_CN:&q ...