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 相关文章推荐
go原生库的中bytes.Buffer用法
Apr 25 Golang
golang 实现并发求和
May 08 Golang
Go语言基础知识点介绍
Jul 04 Golang
Go 语言结构实例分析
Jul 04 Golang
使用GO语言实现Mysql数据库CURD的简单示例
Aug 07 Golang
Golang 并发下的问题定位及解决方案
Mar 16 Golang
Golang 1.18 多模块Multi-Module工作区模式的新特性
Apr 11 Golang
golang使用map实现去除重复数组
Apr 14 Golang
Golang 链表的学习和使用
Apr 19 Golang
Golang 入门 之url 包
May 04 Golang
Go语言编译原理之源码调试
Aug 05 Golang
Go结合Gin导出Mysql数据到Excel表格
Aug 05 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
memcached 和 mysql 主从环境下php开发代码详解
2010/05/16 PHP
php学习之简单计算器实现代码
2011/06/09 PHP
使用PHP+AJAX让WordPress动态加载文章的教程
2015/12/11 PHP
VBS通过WMI监视注册表变动的代码
2011/10/27 Javascript
圣诞节Merry Christmas给博客添加浪漫的下雪效果基于jquery实现
2012/12/27 Javascript
javascript数组遍历for与for in区别详解
2014/12/04 Javascript
Jquery ajax请求导出Excel表格的实现代码
2016/06/08 Javascript
基于javascript实现的快速排序
2016/12/02 Javascript
JS中静态页面实现微信分享功能
2017/02/06 Javascript
ES6新特性之变量和字符串用法示例
2017/04/01 Javascript
微信小程序实现全国机场索引列表
2018/01/31 Javascript
Vue写一个简单的倒计时按钮功能
2018/04/20 Javascript
vue中的$emit 与$on父子组件与兄弟组件的之间通信方式
2018/05/13 Javascript
Vue render函数实战之实现tabs选项卡组件
2019/04/22 Javascript
帮你彻底搞懂JS中的prototype、__proto__与constructor(图解)
2019/08/23 Javascript
vue图片加载失败时用默认图片替换的方法
2019/08/29 Javascript
layui prompt 设置允许空白提交的方法
2019/09/24 Javascript
vue实现图片上传预览功能
2019/12/23 Javascript
VSCode Vue开发推荐插件和VSCode快捷键(小结)
2020/08/08 Javascript
JavaScript构造函数原理及实现流程解析
2020/11/19 Javascript
Python实现基本线性数据结构
2016/08/22 Python
Django模板变量如何传递给外部js调用的方法小结
2017/07/24 Python
Python数据结构与算法之常见的分配排序法示例【桶排序与基数排序】
2017/12/15 Python
pywinauto自动化操作记事本
2019/08/26 Python
python实现的按要求生成手机号功能示例
2019/10/08 Python
Python转换itertools.chain对象为数组的方法
2020/02/07 Python
python通用读取vcf文件的类(复制粘贴即可用)
2020/02/29 Python
使用Python合成图片的实现代码(图片添加个性化文本,图片上叠加其他图片)
2020/04/30 Python
Pytorch 解决自定义子Module .cuda() tensor失败的问题
2020/06/23 Python
Python三维绘图之Matplotlib库的使用方法
2020/09/20 Python
C#面试题问题集
2016/04/02 面试题
年度考核评语
2014/01/19 职场文书
优质服务活动实施方案
2014/05/02 职场文书
小学标准化建设汇报材料
2014/08/16 职场文书
运动会加油稿
2015/07/22 职场文书
python 实现德洛内三角剖分的操作
2021/04/22 Python