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判断key是否在map中的代码
Apr 24 Golang
golang http使用踩过的坑与填坑指南
Apr 27 Golang
go结构体嵌套的切片数组操作
Apr 28 Golang
对Golang中的FORM相关字段理解
May 02 Golang
Golang 编译成DLL文件的操作
May 06 Golang
golang switch语句的灵活写法介绍
May 06 Golang
Go语言空白表示符_的实例用法
Jul 04 Golang
使用GO语言实现Mysql数据库CURD的简单示例
Aug 07 Golang
Golang原生rpc(rpc服务端源码解读)
Apr 07 Golang
golang三种设计模式之简单工厂、方法工厂和抽象工厂
Apr 10 Golang
Golang日志包的使用
Apr 20 Golang
Go调用Rust方法及外部函数接口前置
Jun 14 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的ob_start来生成静态页面的方法分析
2011/03/09 PHP
PHP数据库万能引擎类adodb配置使用以及实例集锦
2014/06/12 PHP
Thinkphp使用mongodb数据库实现多条件查询方法
2014/06/26 PHP
php实现的http请求封装示例
2016/11/08 PHP
关于laravel后台模板laravel-admin select框的使用详解
2019/10/03 PHP
PHP pthreads v3在centos7平台下的安装与配置操作方法
2020/02/21 PHP
不一样的文字闪烁 轮番闪烁
2009/11/11 Javascript
js获取客户端外网ip的简单实例
2013/11/21 Javascript
js生成随机数之random函数随机示例
2013/12/20 Javascript
js出生日期 年月日级联菜单示例代码
2014/01/10 Javascript
嵌入式iframe子页面与父页面js通信的方法
2015/01/20 Javascript
javascript实现画不相交的圆
2015/04/07 Javascript
jquery mobile 移动web(5)
2015/12/20 Javascript
Javascript实现Array和String互转换的方法
2015/12/21 Javascript
WordPress中利用AJAX异步获取评论用户头像的方法
2016/01/08 Javascript
Jquery Easyui自定义下拉框组件使用详解(21)
2020/12/31 Javascript
js实现交通灯效果
2017/01/13 Javascript
使用D3.js制作图表详解
2017/08/13 Javascript
react-native滑动吸顶效果的实现过程
2019/06/03 Javascript
vue Tab切换以及缓存页面处理的几种方式
2019/11/05 Javascript
Vue+Node服务器查询Mongo数据库及页面数据传递操作实例分析
2019/12/20 Javascript
vue项目中在可编辑div光标位置插入内容的实现代码
2020/01/07 Javascript
[02:26]2018DOTA2亚洲邀请赛赛前采访-Newbee篇
2018/04/03 DOTA
python获取指定网页上所有超链接的方法
2015/04/04 Python
机器学习python实战之手写数字识别
2017/11/01 Python
利用python的socket发送http(s)请求方法示例
2018/05/07 Python
解决nohup执行python程序log文件写入不及时的问题
2019/01/14 Python
利用ImageAI库只需几行python代码实现目标检测
2019/08/09 Python
python3.7 利用函数os pandas利用excel对文件名进行归类
2019/09/29 Python
Python通过socketserver处理多个链接
2020/03/18 Python
Ann Taylor官方网站:美国最大的女性产品制造商之一
2016/09/14 全球购物
关于Java String的一道面试题
2013/09/29 面试题
母亲节演讲稿
2014/05/27 职场文书
做一个有道德的人活动方案
2014/08/25 职场文书
群众路线个人对照检查材料2014
2014/09/26 职场文书
Spring中的使用@Async异步调用方法
2021/11/01 Java/Android