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.

92 lines
1.9 KiB

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