未验证 提交 6e6b4885 编写于 作者: Mr.奇淼('s avatar Mr.奇淼( 提交者: GitHub

Merge pull request #631 from songzhibin97/gva_gormv2_dev

feat:插件模式尝鲜
package example
import "github.com/gin-gonic/gin"
type Plugin struct {
}
func (*Plugin) Register(group *gin.RouterGroup) {
group.GET("hello", func(context *gin.Context) {
context.JSON(200, "hello world")
})
}
func (*Plugin) RouterPath() string {
return "group"
}
package plugin
import (
"plugin"
"sync"
"github.com/gin-gonic/gin"
)
const (
OnlyFuncName = "Plugin"
)
var ManagementPlugin = managementPlugin{mp: make(map[string]*plugin.Plugin)}
type managementPlugin struct {
mp map[string]*plugin.Plugin
sync.Mutex
}
func (m *managementPlugin) SetPlugin(key string, p *plugin.Plugin) {
m.Lock()
defer m.Unlock()
m.mp[key] = p
}
func (m *managementPlugin) GetPlugin(key string) (p *plugin.Plugin, ok bool) {
m.Lock()
defer m.Unlock()
p, ok = m.mp[key]
return
}
// Plugin 插件模式接口化
type Plugin interface {
// Register 注册路由
Register(group *gin.RouterGroup)
// RouterPath 用户返回注册路由
RouterPath() string
}
//+build !windows
package plugin
import (
"errors"
"fmt"
"io/fs"
"io/ioutil"
"os"
"path/filepath"
"plugin"
)
// LoadPlugin 加载插件 传入path
func LoadPlugin(path string) error {
path, err := filepath.Abs(path)
if err != nil {
return err
}
fileInfo, err := os.Stat(path)
if err != nil {
return err
}
if fileInfo.IsDir() {
fileSlice, err := ioutil.ReadDir(path)
if err != nil {
return err
}
for _, ff := range fileSlice {
if !ff.IsDir() && filepath.Ext(ff.Name()) == ".so" {
if err = loadPlugin(path, ff); err != nil {
return err
}
} else if ff.IsDir() {
_ = LoadPlugin(filepath.Join(path, ff.Name()))
}
}
return nil
} else {
return loadPlugin(path, fileInfo)
}
}
func loadPlugin(path string, f fs.FileInfo) error {
if filepath.Ext(f.Name()) == ".so" {
fPath := filepath.Join(path, f.Name())
// 加载插件
p, err := plugin.Open(fPath)
if err != nil {
fmt.Println("loadPlugin err ", err)
return err
}
// 判断是否满足协议
// 要满足 OnlyFuncName && 实现 Plugin 接口
if v, err := p.Lookup(OnlyFuncName); err != nil {
fmt.Println("loadPlugin err ", err)
return err
} else if _, ok := v.(Plugin); !ok {
fmt.Println("loadPlugin err ", fmt.Sprintf("path:%s 没有实现 %s 接口", filepath.Base(fPath), OnlyFuncName))
return errors.New("没有实现指定接口")
} else {
}
fmt.Println("loadPlugin add ", filepath.Base(fPath))
ManagementPlugin.SetPlugin(filepath.Base(fPath), p)
}
return nil
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册