Go Plugins插件的实现方式


Posted in Golang onAugust 07, 2021

官方实现

golang 1.8 及以上版本提供了一个创建共享库(shared object)的新工具,称为 Plugins。目前 Plugins 仅在 Linux、FreeBSD 和 macOS 上受支持,且只支持 golang 调用。​

使用示例,定义一个 plugin.go

package main

import (
 "log"
)

func init() {
 log.Println("plugin init")
}

type SayHello struct {
}

func (s *SayHello) CallMe(name string) string {
 log.Println("hello ", name)
 return "I am plugin"
}

// SayHelloPlugin 导出变量
var SayHelloPlugin SayHello

使用 -buildmode=plugin 模式编译出 plugin.so 共享库

go build -o plugin.so -buildmode=plugin plugin.go

main.go 中调用插件:

package main

import (
 "log"
 "plugin"
)

type CustomPlugin interface {
 CallMe(name string) string
}

func main() {
 // 打开插件(并发安全)
 p, err := plugin.Open("plugin.so")
 if err != nil {
  panic(err)
 }
 // 在插件中搜索可导出的变量或函数
 sayHelloPlugin, err := p.Lookup("SayHelloPlugin")
 if err != nil {
  panic(err)
 }
 // 断言插件类型
 if sayHello, ok := sayHelloPlugin.(CustomPlugin); ok {
  log.Println(sayHello.CallMe("togettoyou"))
 }
}
go run main.go

# 输出
2021/07/28 17:07:21 plugin init
2021/07/28 17:07:21 hello  togettoyou
2021/07/28 17:07:21 I am plugin

定义一个插件总结:

  •  
    package 包名需要定义为 main
  • 必须有可导出的变量或函数
  • 不需要 main 函数
  • 插件加载时会先执行 init 函数

Traefik Yaegi 实现

Yaegi 是 Traefik 开源的 Go 解释器。Traefik 自身的插件实现就是使用的 Yaegi 。​

Yaegi 运行在 Go 运行时之上,可以直接作为嵌入式解释器,或使用交互式 shell ,解释运行 Go 代码。不过只支持 Go 1.15 和 Go 1.16(最新的 2 个主要版本)。

创建代码目录结构如下:

│  go.mod
│  go.sum
│  main.go
│
└─plugin
    └─src
        └─hello
                go.mod
                hello.go

这里有个注意点,Yaegi 的插件需要放在 src 目录下。​

其中 hello.go 代码:

package hello

import (
 "fmt"
)

func init() {
 fmt.Println("hello plugin init")
}

func CallMe(msg string) string {
 fmt.Println(msg)
 return "I am plugin"
}

main.go 代码:

package main

import (
 "fmt"
 "github.com/traefik/yaegi/interp"
 "github.com/traefik/yaegi/stdlib"
)

func main() {
 // 初始化解释器
 i := interp.New(interp.Options{GoPath: "./plugin/"})

 // 插件需要使用标准库
 if err := i.Use(stdlib.Symbols); err != nil {
  panic(err)
 }

 // 导入 hello 包
 if _, err := i.Eval(`import "hello"`); err != nil {
  panic(err)
 }

 // 调用 hello.CallMe
 v, err := i.Eval("hello.CallMe")
 if err != nil {
  panic(err)
 }
 callMe := v.Interface().(func(string) string)
 fmt.Println(callMe("togettoyou"))
}
go run main.go

# 输出
hello plugin init
togettoyou
I am plugin

到此这篇关于Go Plugins插件的实现方式的文章就介绍到这了,更多相关Go Plugins插件内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Golang 相关文章推荐
解决Golang time.Parse和time.Format的时区问题
Apr 29 Golang
解决Go gorm踩过的坑
Apr 30 Golang
Go语言 go程释放操作(退出/销毁)
Apr 30 Golang
golang协程池模拟实现群发邮件功能
May 02 Golang
golang日志包logger的用法详解
May 05 Golang
Golang二维数组的使用方式
May 28 Golang
Go timer如何调度
Jun 09 Golang
go select编译期的优化处理逻辑使用场景分析
Jun 28 Golang
Go 通过结构struct实现接口interface的问题
Oct 05 Golang
Go语言实现一个简单的并发聊天室的项目实战
Mar 18 Golang
GoFrame gredis缓存DoVar Conn连接对象 自动序列化GoFrame gredisDo/DoVar方法Conn连接对象自动序列化/反序列化总结
Jun 14 Golang
Go本地测试解耦任务拆解及沟通详解Go本地测试的思路沟通的重要性总结
Jun 21 Golang
使用GO语言实现Mysql数据库CURD的简单示例
Aug 07 #Golang
go使用Gin框架利用阿里云实现短信验证码功能
Aug 04 #Golang
手把手教你导入Go语言第三方库
Aug 04 #Golang
Go语言实现Base64、Base58编码与解码
Jul 26 #Golang
golang内置函数len的小技巧
Jul 25 #Golang
修改并编译golang源码的操作步骤
Go语言应该什么情况使用指针
Jul 25 #Golang
You might like
提升PHP速度全攻略
2006/10/09 PHP
discuz安全提问算法
2007/06/06 PHP
PHP学习之字符串比较和查找
2011/04/17 PHP
PHP通过CURL实现定时任务的图片抓取功能示例
2016/10/03 PHP
prototype 的说明 js类
2006/09/07 Javascript
javascript 有用的脚本函数
2009/05/07 Javascript
javascript 选择文件夹对话框(web)
2009/07/07 Javascript
jQuery ajax cache缓存问题
2010/07/01 Javascript
JavaScript中链式调用之研习
2011/04/07 Javascript
使用js的replace()方法查找字符示例代码
2013/10/28 Javascript
利用javaScript实现点击输入框弹出窗体选择信息
2013/12/11 Javascript
js取float型小数点后两位数的方法
2014/01/18 Javascript
jquery css 设置table的奇偶行背景色示例
2014/06/03 Javascript
JavaScript数据类型之基本类型和引用类型的值
2015/04/01 Javascript
jQuery与getJson结合的用法实例
2015/08/07 Javascript
javascript实现支持移动设备画廊
2015/08/24 Javascript
将json转换成struts参数的方法
2016/11/08 Javascript
vue使用ElementUI时导航栏默认展开功能的实现
2018/07/04 Javascript
如何封装了一个vue移动端下拉加载下一页数据的组件
2019/01/06 Javascript
vue中监听路由参数的变化及方法
2019/12/06 Javascript
Python中的自定义函数学习笔记
2014/09/23 Python
使用Python发送邮件附件以定时备份MySQL的教程
2015/04/25 Python
Python实现对excel文件列表值进行统计的方法
2015/07/25 Python
用pickle存储Python的原生对象方法
2017/04/28 Python
Python2.7基于笛卡尔积算法实现N个数组的排列组合运算示例
2017/11/23 Python
PyQt5每天必学之切换按钮
2020/08/20 Python
使用python将请求的requests headers参数格式化方法
2019/01/02 Python
详解pyppeteer(python版puppeteer)基本使用
2019/06/12 Python
使用Python进行中文繁简转换的实现代码
2019/10/18 Python
python实现输入任意一个大写字母生成金字塔的示例
2019/10/27 Python
Python多线程及其基本使用方法实例分析
2019/10/29 Python
wxPython实现文本框基础组件
2019/11/18 Python
初探CSS3中的calc()功能
2015/07/14 HTML / CSS
运动会宣传口号
2014/06/09 职场文书
2014年财务个人工作总结
2014/12/08 职场文书
Windows环境下实现批量执行Sql文件
2021/10/05 SQL Server