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 25 Golang
彻底理解golang中什么是nil
Apr 29 Golang
Golang 如何实现函数的任意类型传参
Apr 29 Golang
go语言中fallthrough的用法说明
May 06 Golang
go goroutine 怎样进行错误处理
Jul 16 Golang
Golang并发操作中常见的读写锁详析
Aug 30 Golang
Go语言特点及基本数据类型使用详解
Mar 21 Golang
Golang流模式之grpc的四种数据流
Apr 13 Golang
golang使用map实现去除重复数组
Apr 14 Golang
Golang日志包的使用
Apr 20 Golang
Go web入门Go pongo2模板引擎
May 20 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网页显示各种语法错误
2013/09/23 PHP
PHP去掉json字符串中的反斜杠\及去掉双引号前的反斜杠
2015/09/30 PHP
在WordPress的文章编辑器中设置默认内容的方法
2015/12/29 PHP
PHP爬虫之百万级别知乎用户数据爬取与分析
2016/01/22 PHP
php异步:在php中使用fsockopen curl实现类似异步处理的功能方法
2016/12/10 PHP
Thinkphp5.0 框架Model模型简单用法分析
2019/10/11 PHP
使用Git实现Laravel项目的自动化部署
2019/11/24 PHP
laravel框架模型和数据库基础操作实例详解
2020/01/25 PHP
document.all与WEB标准
2020/05/13 Javascript
innerHTML与jquery里的html()区别介绍
2012/10/12 Javascript
javascript调试之DOM断点调试法使用技巧分享
2014/04/15 Javascript
7个让JavaScript变得更好的注意事项
2015/01/28 Javascript
在Javascript中处理字符串之big()方法的使用
2015/06/08 Javascript
JavaScript中日期函数的相关操作知识
2016/08/03 Javascript
jQuery插件ajaxFileUpload使用详解
2017/01/10 Javascript
jQuery extend()详解及简单实例
2017/05/06 jQuery
JS检测是否可以访问公网服务器功能代码
2017/06/19 Javascript
解决淘宝cnpm 安装后cnpm不是内部或外部命令的问题
2018/05/17 Javascript
JS的函数调用栈stack size的计算方法
2018/06/24 Javascript
js逆向解密之网络爬虫
2019/05/30 Javascript
vue+koa2实现session、token登陆状态验证的示例
2019/08/30 Javascript
python实现在windows下操作word的方法
2015/04/28 Python
在Python的Django框架中获取单个对象数据的简单方法
2015/07/17 Python
最近Python有点火? 给你7个学习它的理由!
2017/06/26 Python
python实现感知机线性分类模型示例代码
2019/06/02 Python
Django实现auth模块下的登录注册与注销功能
2019/10/10 Python
基于python3.7利用Motor来异步读写Mongodb提高效率(推荐)
2020/04/29 Python
django queryset相加和筛选教程
2020/05/18 Python
巴西最大的家具及装饰用品店:Mobly
2017/10/11 全球购物
计算机科学与技术应届生求职信
2013/11/07 职场文书
园林设计师自荐信
2013/11/18 职场文书
工程部经理岗位职责
2013/12/08 职场文书
自我评价的写作规则
2014/01/06 职场文书
学生思想表现的评语
2014/01/30 职场文书
Python实现抖音热搜定时爬取功能
2022/03/16 Python
vue ant design 封装弹窗表单的使用
2022/06/01 Vue.js