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 相关文章推荐
goland 清除所有的默认设置操作
Apr 28 Golang
使用Golang的channel交叉打印两个数组的操作
Apr 29 Golang
go类型转换及与C的类型转换方式
May 05 Golang
GoLang中生成UUID唯一标识的实现
May 08 Golang
Go 语言下基于Redis分布式锁的实现方式
Jun 28 Golang
golang 实用库gotable的具体使用
Jul 01 Golang
Go语言基础map用法及示例详解
Nov 17 Golang
浅谈GO中的Channel以及死锁的造成
Mar 18 Golang
Go语言的协程上下文的几个方法和用法
Apr 11 Golang
Golang gRPC HTTP协议转换示例
Jun 16 Golang
Go中使用gjson来操作JSON数据的实现
Aug 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 分页原理分析,大家可以看看
2009/12/21 PHP
Codeigniter发送邮件的方法
2015/03/19 PHP
PHP Oauth授权和本地加密实现方法
2016/08/12 PHP
[原创]网络复制内容时常用的正则+editplus
2006/11/30 Javascript
IE/FireFox具备兼容性的拖动代码
2007/08/13 Javascript
避免 showModalDialog 弹出新窗体的原因分析
2010/05/31 Javascript
Jquery 的扩展方法总结
2011/10/01 Javascript
JS 获取滚动条高度示例代码
2013/10/24 Javascript
JavaScript实现的购物车效果可以运用在好多地方
2014/05/09 Javascript
node.js+Ajax实现获取HTTP服务器返回数据
2014/11/26 Javascript
JS实现两表格里数据来回转移的方法
2015/05/28 Javascript
Bootstrap组件(一)之菜单
2016/05/11 Javascript
Javascript基础知识盲点总结之函数
2016/05/15 Javascript
Jquery组件easyUi实现表单验证示例
2016/08/23 Javascript
深入理解vue.js中的v-if和v-show
2017/06/22 Javascript
vue-router项目实战总结篇
2018/02/11 Javascript
JS获取子节点、父节点和兄弟节点的方法实例总结
2018/07/06 Javascript
JavaScript对象拷贝与赋值操作实例分析
2018/12/10 Javascript
jQuery中使用validate插件校验表单功能
2019/05/24 jQuery
微信小程序服务器日期格式化问题
2020/01/07 Javascript
vue2路由基本用法实例分析
2020/03/06 Javascript
viewer.js一个强大的基于jQuery的图像查看插件(支持旋转、缩放)
2020/04/01 jQuery
Vue实现浏览器打印功能的代码
2020/04/17 Javascript
通过实例解析JavaScript for in及for of区别
2020/06/15 Javascript
python网络编程学习笔记(三):socket网络服务器
2014/06/09 Python
整理Python 常用string函数(收藏)
2016/05/30 Python
python之文件读取一行一行的方法
2018/07/12 Python
Python tkinter 下拉日历控件代码
2020/03/04 Python
python 第三方库paramiko的常用方式
2021/02/20 Python
腾讯公司的一个sql题
2013/01/22 面试题
行政总监岗位职责
2013/12/05 职场文书
少年闰土教学反思
2014/02/22 职场文书
幼儿园毕业园长感言
2014/02/24 职场文书
爱国主义教育活动总结
2014/05/07 职场文书
2014保险公司个人工作总结
2014/12/09 职场文书
Python绘制散乱的点构成的图的方法
2022/04/21 Python