最新下载
热门教程
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 
Go Plugins插件的实现方式代码示例
时间:2022-06-25 01:48:34 编辑:袖梨 来源:一聚教程网
本篇文章小编给大家分享一下Go Plugins插件的实现方式代码示例,文章代码介绍的很详细,小编觉得挺不错的,现在分享给大家供大家参考,有需要的小伙伴们可以来看看。
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
相关文章
- 重返未来1999贝丽尔塑造抽取建议 11-04
 - 逃离塔科夫兑换码怎么用 逃离塔科夫最新兑换码大全 11-04
 - Dark Quest4兑换码是什么 黑暗探险4兑换码大全分享 11-04
 - 梦魇之王NIGHTMARE兑换码分享 梦魇之王最新兑换码大全 11-04
 - 洛克王国世界翼王技能怎么搭配-圣羽翼王技能搭配推荐 11-04
 - 逃离鸭科夫热门实用的MOD推荐 一键提升游戏体验! 11-04