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通过递归遍历生成树状结构的操作
Apr 28 Golang
解决golang在import自己的包报错的问题
Apr 29 Golang
golang日志包logger的用法详解
May 05 Golang
go语言中GOPATH GOROOT的作用和设置方式
May 05 Golang
浅谈Golang 切片(slice)扩容机制的原理
Jun 09 Golang
浅谈Go语言多态的实现与interface使用
Jun 16 Golang
基于Go语言构建RESTful API服务
Jul 25 Golang
Go语言实现Base64、Base58编码与解码
Jul 26 Golang
victoriaMetrics库布隆过滤器初始化及使用详解
Apr 05 Golang
Golang bufio详细讲解
Apr 21 Golang
Python测试框架pytest核心库pluggy详解
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
php设计模式 Delegation(委托模式)
2011/06/26 PHP
php中的常用魔术方法总结
2013/08/02 PHP
php使用自定义函数实现汉字分割替换功能示例
2017/01/30 PHP
JS解析XML的实现代码
2009/11/12 Javascript
filters.revealTrans.Transition使用方法小结
2010/08/19 Javascript
JavaScript运行过程中的“预编译阶段”和“执行阶段”
2015/12/16 Javascript
原生js制作日历控件实例分享
2016/04/06 Javascript
用js动态添加html元素,以及属性的简单实例
2016/07/19 Javascript
jQuery的ajax和遍历数组json实例代码
2016/08/01 Javascript
AngularJs  unit-testing(单元测试)详解
2016/09/02 Javascript
jQuery轮播图效果精简版完整示例
2016/09/04 Javascript
Java与JavaScript中判断两字符串是否相等的区别
2017/03/13 Javascript
浅谈对Angular中的生命周期钩子的理解
2017/07/31 Javascript
Vue的MVVM实现方法
2017/08/16 Javascript
layer.confirm取消按钮绑定事件的方法
2018/08/17 Javascript
js form表单input框限制20个字符,10个汉字代码实例
2019/04/12 Javascript
Python实现并行抓取整站40万条房价数据(可更换抓取城市)
2016/12/14 Python
Python编程给numpy矩阵添加一列方法示例
2017/12/04 Python
根据DataFrame某一列的值来选择具体的某一行方法
2018/07/03 Python
pip安装提示Twisted错误问题(Python3.6.4安装Twisted错误)
2020/05/09 Python
pycharm如何使用anaconda中的各种包(操作步骤)
2020/07/31 Python
HTML5各种头部meta标签的功能(推荐)
2017/03/13 HTML / CSS
HTML5 LocalStorage 本地存储详细概括(多图)
2017/08/18 HTML / CSS
Banggood官网:面向全球客户的综合商城
2017/04/19 全球购物
最耐用行李箱,一箱永流传:Briggs & Riley(全球终身保修)
2017/12/07 全球购物
波兰多品牌运动商店:StreetStyle24.pl
2020/09/22 全球购物
劳动实践课感言
2014/02/01 职场文书
鼓励运动员的广播稿
2014/02/08 职场文书
职业培训师职业生涯规划
2014/02/18 职场文书
怎么写好自荐书
2014/03/02 职场文书
推荐信格式范文
2014/05/09 职场文书
干部鉴定材料
2014/05/18 职场文书
2014县政府领导班子对照检查材料思想汇报
2014/09/25 职场文书
房地产销售经理岗位职责
2015/02/02 职场文书
大一学生个人总结
2015/02/15 职场文书
pandas中DataFrame重置索引的几种方法
2021/05/24 Python