You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

90 lines
1.9 KiB

  1. //+build !windows
  2. package plugin
  3. import (
  4. "errors"
  5. "fmt"
  6. "io/fs"
  7. "io/ioutil"
  8. "os"
  9. "path/filepath"
  10. "plugin"
  11. "sync"
  12. )
  13. var ManagementPlugin = managementPlugin{mp: make(map[string]*plugin.Plugin)}
  14. type managementPlugin struct {
  15. mp map[string]*plugin.Plugin
  16. sync.Mutex
  17. }
  18. func (m *managementPlugin) SetPlugin(key string, p *plugin.Plugin) {
  19. m.Lock()
  20. defer m.Unlock()
  21. m.mp[key] = p
  22. }
  23. func (m *managementPlugin) GetPlugin(key string) (p *plugin.Plugin, ok bool) {
  24. m.Lock()
  25. defer m.Unlock()
  26. p, ok = m.mp[key]
  27. return
  28. }
  29. // LoadPlugin 加载插件 传入path
  30. func LoadPlugin(path string) error {
  31. path, err := filepath.Abs(path)
  32. if err != nil {
  33. return err
  34. }
  35. fileInfo, err := os.Stat(path)
  36. if err != nil {
  37. return err
  38. }
  39. if fileInfo.IsDir() {
  40. fileSlice, err := ioutil.ReadDir(path)
  41. if err != nil {
  42. return err
  43. }
  44. for _, ff := range fileSlice {
  45. if !ff.IsDir() && filepath.Ext(ff.Name()) == ".so" {
  46. if err = loadPlugin(path, ff); err != nil {
  47. return err
  48. }
  49. } else if ff.IsDir() {
  50. _ = LoadPlugin(filepath.Join(path, ff.Name()))
  51. }
  52. }
  53. return nil
  54. } else {
  55. return loadPlugin(path, fileInfo)
  56. }
  57. }
  58. func loadPlugin(path string, f fs.FileInfo) error {
  59. if filepath.Ext(f.Name()) == ".so" {
  60. fPath := filepath.Join(path, f.Name())
  61. // 加载插件
  62. p, err := plugin.Open(fPath)
  63. if err != nil {
  64. fmt.Println("loadPlugin err ", err)
  65. return err
  66. }
  67. // 判断是否满足协议
  68. // 要满足 OnlyFuncName && 实现 Plugin 接口
  69. if v, err := p.Lookup(OnlyFuncName); err != nil {
  70. fmt.Println("loadPlugin err ", err)
  71. return err
  72. } else if _, ok := v.(Plugin); !ok {
  73. fmt.Println("loadPlugin err ", fmt.Sprintf("path:%s 没有实现 %s 接口", filepath.Base(fPath), OnlyFuncName))
  74. return errors.New("没有实现指定接口")
  75. } else {
  76. }
  77. fmt.Println("loadPlugin add ", filepath.Base(fPath))
  78. ManagementPlugin.SetPlugin(filepath.Base(fPath), p)
  79. }
  80. return nil
  81. }