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缓冲channel和非缓冲channel的区别说明
Apr 25 Golang
golang正则之命名分组方式
Apr 25 Golang
goland 恢复已更改文件的操作
Apr 28 Golang
golang DNS服务器的简单实现操作
Apr 30 Golang
解决Golang中goroutine执行速度的问题
May 02 Golang
浅谈golang 中time.After释放的问题
May 05 Golang
Go语言基础知识点介绍
Jul 04 Golang
Go语言实现Base64、Base58编码与解码
Jul 26 Golang
Go语言grpc和protobuf
Apr 13 Golang
Golang实现可重入锁的示例代码
May 25 Golang
详解Go语言中Get/Post请求测试
Jun 01 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
通用PHP动态生成静态HTML网页的代码
2010/03/04 PHP
PHP isset()与empty()的使用区别详解
2010/08/29 PHP
探讨:array2xml和xml2array以及xml与array的互相转化
2013/06/24 PHP
让图片旋转任意角度及JQuery插件使用介绍
2013/03/20 Javascript
JQuery实现绚丽的横向下拉菜单
2013/12/19 Javascript
简单的jquery左侧导航栏和页面选中效果
2014/08/21 Javascript
使用javascript将时间转换成今天,昨天,前天等格式
2015/06/25 Javascript
微信小程序 富文本转文本实例详解
2016/10/24 Javascript
javascript显示系统当前时间代码
2016/12/29 Javascript
JavaScript实现自动跳转文本功能
2017/05/25 Javascript
二维码图片生成器QRCode.js简单介绍
2017/08/18 Javascript
[原创]jquery判断元素内容是否为空的方法
2018/05/04 jQuery
vue解决一个方法同时发送多个请求的问题
2018/09/25 Javascript
图文讲解vue的v-if使用方法
2019/02/11 Javascript
elementUI vue this.$confirm 和el-dialog 弹出框 移动 示例demo
2019/07/03 Javascript
Python中使用ConfigParser解析ini配置文件实例
2014/08/30 Python
Python for Informatics 第11章之正则表达式(二)
2016/04/21 Python
python使用pycharm环境调用opencv库
2018/02/11 Python
Python中collections模块的基本使用教程
2018/12/07 Python
在numpy矩阵中令小于0的元素改为0的实例
2019/01/26 Python
Python 类方法和实例方法(@classmethod),静态方法(@staticmethod)原理与用法分析
2019/09/20 Python
PyTorch中Tensor的数据统计示例
2020/02/17 Python
在django中使用post方法时,需要增加csrftoken的例子
2020/03/13 Python
python 多线程死锁问题的解决方案
2020/08/25 Python
Python提取视频中图片的示例(按帧、按秒)
2020/10/22 Python
使用Python快速打开一个百万行级别的超大Excel文件的方法
2021/03/02 Python
使用HTML5在网页中嵌入音频和视频播放的基本方法
2016/02/22 HTML / CSS
建筑工程专业学生的自我评价
2013/12/25 职场文书
实习生自我评价
2014/01/18 职场文书
JAVA程序员自荐书
2014/01/30 职场文书
事业单位分类改革实施方案
2014/03/21 职场文书
科技工作者先进事迹
2014/08/16 职场文书
七一建党节演讲稿
2014/09/11 职场文书
中国世界遗产导游词
2015/02/13 职场文书
MySQL为数据表建立索引的原则详解
2022/03/03 MySQL