Go Plugins插件的實現(xiàn)方式
官方實現(xiàn)
golang 1.8 及以上版本提供了一個創(chuàng)建共享庫(shared object)的新工具,稱為 Plugins。目前 Plugins 僅在 Linux、FreeBSD 和 macOS 上受支持,且只支持 golang 調(diào)用。
使用示例,定義一個 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 導(dǎo)出變量
var SayHelloPlugin SayHello
使用 -buildmode=plugin 模式編譯出 plugin.so 共享庫
go build -o plugin.so -buildmode=plugin plugin.go
main.go 中調(diào)用插件:
package main
import (
"log"
"plugin"
)
type CustomPlugin interface {
CallMe(name string) string
}
func main() {
// 打開插件(并發(fā)安全)
p, err := plugin.Open("plugin.so")
if err != nil {
panic(err)
}
// 在插件中搜索可導(dǎo)出的變量或函數(shù)
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
定義一個插件總結(jié):
- package 包名需要定義為 main
- 必須有可導(dǎo)出的變量或函數(shù)
- 不需要 main 函數(shù)
- 插件加載時會先執(zhí)行 init 函數(shù)
Traefik Yaegi 實現(xiàn)
Yaegi 是 Traefik 開源的 Go 解釋器。Traefik 自身的插件實現(xiàn)就是使用的 Yaegi 。
Yaegi 運行在 Go 運行時之上,可以直接作為嵌入式解釋器,或使用交互式 shell ,解釋運行 Go 代碼。不過只支持 Go 1.15 和 Go 1.16(最新的 2 個主要版本)。
創(chuàng)建代碼目錄結(jié)構(gòu)如下:
│ 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)
}
// 導(dǎo)入 hello 包
if _, err := i.Eval(`import "hello"`); err != nil {
panic(err)
}
// 調(diào)用 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
到此這篇關(guān)于Go Plugins插件的實現(xiàn)方式的文章就介紹到這了,更多相關(guān)Go Plugins插件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
go語言中切片與內(nèi)存復(fù)制 memcpy 的實現(xiàn)操作
這篇文章主要介紹了go語言中切片與內(nèi)存復(fù)制 memcpy 的實現(xiàn)操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-04-04
執(zhí)行g(shù)o?build報錯go:?go.mod?file?not?found?in?current?dir
本文主要為大家介紹了執(zhí)行g(shù)o build報錯go:?go.mod?file?not?found?in?current?directory?or?any?parent?directory解決分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-06-06
Go/C語言LeetCode題解997找到小鎮(zhèn)法官
這篇文章主要為大家介紹了Go語言LeetCode題解997找到小鎮(zhèn)的法官示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-12-12
在 Golang 中實現(xiàn) Cache::remember 方法詳解
這篇文章主要介紹了在 Golang 中實現(xiàn) Cache::remember 方法詳解,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-03-03
Go語言設(shè)計模式之實現(xiàn)觀察者模式解決代碼臃腫
今天學(xué)習(xí)一下用?Go?實現(xiàn)觀察者模式,觀察者模式主要是用來實現(xiàn)事件驅(qū)動編程。事件驅(qū)動編程的應(yīng)用還是挺廣的,除了我們都知道的能夠用來解耦:用戶修改密碼后,給用戶發(fā)短信進行風(fēng)險提示之類的典型場景,在微服務(wù)架構(gòu)實現(xiàn)最終一致性、實現(xiàn)事件源A?+?ES2022-08-08

