golang grpc 插件模板
插件使用grpc
通讯协议。yao
框架已经把大部分的grpc
调用逻辑封装好了。插件只需要实现一个Exec
方法即可。
创建插件
下面以一个简单的例子来说明如何编写一个插件。
在应用的根目录或外部目录创建目录plugins
,再在plugins
下面创建demo
目录。这个目录实际上是一个独立的 golang 项目,只需要在main.go
中实现Exec
方法即可。
sh
mkdir -p plugins/demo
touch plugins/demo/main.go
代码模板:plugins/demo/main.go
go
package main
//插件模板
import (
"encoding/json"
"io"
"os"
"path"
"github.com/hashicorp/go-hclog"
"github.com/yaoapp/kun/grpc"
)
// 定义插件类型,包含grpc.Plugin
type DemoPlugin struct{ grpc.Plugin }
// 设置插件日志到单独的文件
func (demo *DemoPlugin) setLogFile() {
var output io.Writer = os.Stdout
//开启日志
logroot := os.Getenv("GOU_TEST_PLG_LOG")
if logroot == "" {
logroot = "./logs"
}
if logroot != "" {
logfile, err := os.OpenFile(path.Join(logroot, "plugin.log"), os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
if err == nil {
output = logfile
}
}
demo.Plugin.SetLogger(output, grpc.Trace)
}
// 插件执行需要实现的方法
// 参数name是在调用插件时的方法名,比如调用插件demo的Hello方法是的规则是plugins.demo.Hello时。
//
// 注意:name会自动的变成小写
//
// args参数是一个数组,需要在插件中自行解析。判断它的长度与类型,再转入具体的go类型。
//
// Exec 插件入口函数
func (demo *DemoPlugin) Exec(name string, args ...interface{}) (*grpc.Response, error) {
demo.Logger.Log(hclog.Trace, "plugin method called", name)
demo.Logger.Log(hclog.Trace, "args", args)
var v = make(map[string]interface{})
switch name {
case "hello":
if len(args) < 1 {
v = map[string]interface{}{"code": 400, "message": "参数不足,需要一个参数"}
break
}
code, ok := args[0].(string)
if !ok {
v = map[string]interface{}{"code": 400, "message": "参数的类型需要是字符串", "args": args}
} else {
v = map[string]interface{}{"name": "Hello", "value": code}
v["x1"] = map[string]interface{}{"name": "Hello", "value": code}
}
default:
v = map[string]interface{}{"name": name, "args": args}
}
//输出前需要转换成字节
bytes, err := json.Marshal(v)
if err != nil {
return nil, err
}
//设置输出数据的类型
//支持的类型:map/interface/string/integer,int/float,double/array,slice
return &grpc.Response{Bytes: bytes, Type: "map"}, nil
}
// 生成插件时函数名修改成main
func main() {
plugin := &DemoPlugin{}
plugin.setLogFile()
grpc.Serve(plugin)
}
// 调试时开启,需要直接调试时修改成main
func debug() {
plugin := &DemoPlugin{}
plugin.setLogFile()
// grpc.Serve(plugin) 不要使用server
plugin.Exec("hello", "world")//普通的go程序,用于开发调试
}
插件构建
生成的插件文件的后缀名需要是.so 或是.dll。
bash
# 切换到插件目录
cd plugins/demo
# 初始化项目
go mod init main
# 下载依赖
go mod tidy
# 构建制品 linux/macox
go build -o ../demo.so .
# 构建制品 windows
# go build -o ../demo.dll .
# linux/macox 增加执行权限
chmod +x ../demo.so
# 切换到yoa应用目录
cd ../../
# 测试插件功能
yao run plugins.demo.Hello "World"