plugin_uinx.go 1.9 KB
Newer Older
S
songzhibin97 已提交
1 2 3 4 5 6 7 8 9 10 11 12
//+build !windows

package plugin

import (
	"errors"
	"fmt"
	"io/fs"
	"io/ioutil"
	"os"
	"path/filepath"
	"plugin"
S
songzhibin97 已提交
13
	"sync"
S
songzhibin97 已提交
14 15
)

S
songzhibin97 已提交
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
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
}

S
songzhibin97 已提交
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
// 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
}