请选择 进入手机版 | 继续访问电脑版

[Golang] Go Plugins插件的实现方式

[复制链接]
查看115 | 回复13 | 2021-9-15 00:07:22 | 显示全部楼层 |阅读模式

官方实现

golang 1.8 及以上版本提供了一个创建共享库(shared object)的新工具,称为 Plugins。现在 Plugins 仅在 Linux、FreeBSD 和 macOS 上受支持,且只支持 golang 调用。​

使用 示例,定义一个

  1. plugin.go
复制代码

  1. package main
  2. import (
  3. "log"
  4. )
  5. func init() {
  6. log.Println("plugin init")
  7. }
  8. type SayHello struct {
  9. }
  10. func (s *SayHello) CallMe(name string) string {
  11. log.Println("hello ", name)
  12. return "I am plugin"
  13. }
  14. // SayHelloPlugin 导出变量
  15. var SayHelloPlugin SayHello
复制代码

使用

  1. -buildmode=plugin
复制代码
模式编译出
  1. plugin.so
复制代码
共享库

  1. go build -o plugin.so -buildmode=plugin plugin.go
复制代码

  1. main.go
复制代码
中调用插件:

  1. package main
  2. import (
  3. "log"
  4. "plugin"
  5. )
  6. type CustomPlugin interface {
  7. CallMe(name string) string
  8. }
  9. func main() {
  10. // 打开插件(并发安全)
  11. p, err := plugin.Open("plugin.so")
  12. if err != nil {
  13. panic(err)
  14. }
  15. // 在插件中搜索可导出的变量或函数
  16. sayHelloPlugin, err := p.Lookup("SayHelloPlugin")
  17. if err != nil {
  18. panic(err)
  19. }
  20. // 断言插件类型
  21. if sayHello, ok := sayHelloPlugin.(CustomPlugin); ok {
  22. log.Println(sayHello.CallMe("togettoyou"))
  23. }
  24. }
复制代码
  1. go run main.go
  2. # 输出
  3. 2021/07/28 17:07:21 plugin init
  4. 2021/07/28 17:07:21 hello togettoyou
  5. 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 个告急 版本)。

创建代码目次 布局 如下:

  1. │ go.mod
  2. │ go.sum
  3. │ main.go
  4. └─plugin
  5. └─src
  6. └─hello
  7. go.mod
  8. hello.go
复制代码

这里有个注意 点,Yaegi 的插件必要 放在 src 目次 下。​

此中

  1. hello.go
复制代码
代码:

  1. package hello
  2. import (
  3. "fmt"
  4. )
  5. func init() {
  6. fmt.Println("hello plugin init")
  7. }
  8. func CallMe(msg string) string {
  9. fmt.Println(msg)
  10. return "I am plugin"
  11. }
复制代码

  1. main.go
复制代码
代码:

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/traefik/yaegi/interp"
  5. "github.com/traefik/yaegi/stdlib"
  6. )
  7. func main() {
  8. // 初始化解释器
  9. i := interp.New(interp.Options{GoPath: "./plugin/"})
  10. // 插件需要使用标准库
  11. if err := i.Use(stdlib.Symbols); err != nil {
  12. panic(err)
  13. }
  14. // 导入 hello 包
  15. if _, err := i.Eval(`import "hello"`); err != nil {
  16. panic(err)
  17. }
  18. // 调用 hello.CallMe
  19. v, err := i.Eval("hello.CallMe")
  20. if err != nil {
  21. panic(err)
  22. }
  23. callMe := v.Interface().(func(string) string)
  24. fmt.Println(callMe("togettoyou"))
  25. }
复制代码
  1. go run main.go
  2. # 输出
  3. hello plugin init
  4. togettoyou
  5. I am plugin
复制代码

到此这篇关于Go Plugins插件的实现方式的文章就先容 到这了,更多相干 Go Plugins插件内容请搜刮 脚本之家从前 的文章或继续欣赏 下面的相干 文章盼望 大家以后多多支持脚本之家!


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

avatar 意乱了真假意wk | 2021-9-19 13:00:26 | 显示全部楼层
视死如归的架势啊!
回复

使用道具 举报

avatar 123456825 | 2021-9-20 11:06:17 | 显示全部楼层
终于看完了,很不错!
回复

使用道具 举报

avatar 安夕萌mdj | 2021-9-21 16:11:58 | 显示全部楼层
收藏了,以后可能会用到!
回复

使用道具 举报

avatar 遨瀚 | 2021-10-6 06:00:12 | 显示全部楼层
强,我和我的小伙伴们都惊呆了!
回复

使用道具 举报

admin楼主的病已经好了百分之六十二了!
回复

使用道具 举报

今天怎么了,什么人都出来了!
回复

使用道具 举报

信admin楼主,得永生!
回复

使用道具 举报

没人理我,好伤心啊!
回复

使用道具 举报

avatar 旭日非常 | 前天 02:02 | 显示全部楼层
admin楼主的帖子提神醒脑啊!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则