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项目中使用init()
Apr 12 Golang
golang判断key是否在map中的代码
Apr 24 Golang
golang http使用踩过的坑与填坑指南
Apr 27 Golang
goland 清除所有的默认设置操作
Apr 28 Golang
golang elasticsearch Client的使用详解
May 05 Golang
解决goland 导入项目后import里的包报红问题
May 06 Golang
Go timer如何调度
Jun 09 Golang
Golang生成Excel文档的方法步骤
Jun 09 Golang
golang操作redis的客户端包有多个比如redigo、go-redis
Apr 14 Golang
GO语言字符串处理函数之处理Strings包
Apr 14 Golang
GO语言异常处理分析 err接口及defer延迟
Apr 14 Golang
Golang获取List列表元素的四种方式
Apr 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
2006/12/14 PHP
关于PHP session 存储方式的详细介绍
2013/06/25 PHP
PHP Global定义全局变量使用说明
2013/08/15 PHP
php将csv文件导入到mysql数据库的方法
2014/12/24 PHP
通过php添加xml文档内容的方法
2015/01/23 PHP
PHP输入输出流学习笔记
2015/05/12 PHP
理解PHP中的Session及对Session有效期的控制
2016/01/08 PHP
PHP与服务器文件系统的简单交互
2016/10/21 PHP
laravel实现登录时监听事件,添加登录用户的记录方法
2019/09/30 PHP
Aster vs Newbee BO3 第二场2.18
2021/03/10 DOTA
使用jquery为table动态添加行的实现代码
2011/03/30 Javascript
JavaScript学习心得之概述
2015/01/20 Javascript
jQuery三级下拉列表导航菜单代码分享
2020/04/15 Javascript
JavaScript常用数组算法小结
2016/02/13 Javascript
jQuery解决IE6、7、8不能使用 JSON.stringify 函数的问题
2016/05/31 Javascript
深入理解javascript作用域第二篇之词法作用域和动态作用域
2016/07/24 Javascript
Js 获取、判断浏览器版本信息的简单方法
2016/08/08 Javascript
纯js实现手风琴效果代码
2020/04/17 Javascript
js模拟微博发布消息
2017/02/23 Javascript
jQuery实现table中两列CheckBox只能选中一个的示例
2017/09/22 jQuery
微信jssdk逻辑在vue中的运用详解
2018/11/14 Javascript
layui的数据表格+springmvc实现搜索功能的例子
2019/09/28 Javascript
Python标准库之itertools库的使用方法
2017/09/07 Python
linecache模块加载和缓存文件内容详解
2018/01/11 Python
python将字典内容存入mysql实例代码
2018/01/18 Python
详解python实现线程安全的单例模式
2018/03/05 Python
pandas读取CSV文件时查看修改各列的数据类型格式
2019/07/07 Python
win7上tensorflow2.2.0安装成功 引用DLL load failed时找不到指定模块 tensorflow has no attribute xxx 解决方法
2020/05/20 Python
css3+jq创作含苞待放的荷花
2014/02/20 HTML / CSS
香港唯港荟酒店预订:Hotel ICON
2018/03/27 全球购物
一套带网友答案的.NET笔试题
2016/12/06 面试题
员工年终演讲稿
2014/01/03 职场文书
《商鞅南门立木》教学反思
2014/02/16 职场文书
养生餐厅创业计划书范文
2014/03/26 职场文书
机关作风整顿个人剖析材料
2014/10/06 职场文书
使用Redis实现秒杀功能的简单方法
2021/05/08 Redis