参考文章: https://toutiao.io/posts/adjoci/preview
闲来无事,今天发现go居然有一个插件系统。 果然是宇宙级的语言。
plugconf.yaml
plug:
lang: "./pluglib/en.so"
package plug
import (
"github.com/ghodss/yaml"
"io/ioutil"
"plugin"
)
import "xxxxxxx/checkerr"
var GlobalGreeter func() string
type Plugconf struct {
Plug struct {
Lang string
}
}
var GlobalPlugconf *Plugconf
func Load() (err error) {
defer checkerr.MarkPanic(&err)
// 载入配置文件
modByte, err := ioutil.ReadFile("./conf/plugconf.yaml")
checkerr.CheckError(err, "load conf failed", err)
// 解析配置
GlobalPlugconf = new(Plugconf)
err = yaml.Unmarshal(modByte, GlobalPlugconf)
checkerr.CheckError(err, "marshal yaml failed ", err)
// 打开插件
plug, err := plugin.Open(GlobalPlugconf.Plug.Lang)
checkerr.CheckError(err, "open plug failed", err)
// 寻找对象
greeterObj, err := plug.Lookup("Greeter")
checkerr.CheckError(err, "look up failed ", err)
// 转换对象的格式
GlobalGreeter = greeterObj.(func() string)
return nil
}
func RunGreeter() string {
return GlobalGreeter()
}
package main
import (
"fmt"
"main/plug"
"time"
)
func main() {
for {
err := plug.Load()
if err != nil {
fmt.Println(err)
return
}
fmt.Println(plug.RunGreeter())
time.Sleep(time.Second)
}
}
插件需要在main包。比如
package main
type greeter struct {
}
func (g *greeter) Greet() string {
return "世界你好"
}
// 这个就是可导出的函数,插件在lookup这个函数
func Greeter() string {
return new(greeter).Greet()
}
package main
type greeter struct {
}
func (g *greeter) Greet() string {
return "hello world"
}
func Greeter() string {
return new(greeter).Greet()
}
插件代码写好后,必须编译为so Makefile
all:lib
lib:
go build -buildmode=plugin -o ./en.so en.go
go build -buildmode=plugin -o ./ch.so ch.go