【问题标题】:How to solve circular dependency without creating new package?如何在不创建新包的情况下解决循环依赖?
【发布时间】:2022-02-02 22:15:23
【问题描述】:

在 golang 中想要一个具有全局注册表的插件系统。结构可以简化如下:

/plugins/registry.go
/plugins/plugin1/impl.go

registry.go:

package plugins

import "plugins/plugin1" // required for plugin1.MakePlugin

type IPlugin interface {
  Register() error
}

type Factory func(x int) IPlugin

var registry = []Factory{
  plugin1.MakePlugin,
}

impl.go:

package plugin1

import "plugins" // required for IPlugin

type Plugin struct {
  x int
}

func MakePlugin(x int) plugins.IPlugin {
  return &Plugin{
    x: x,
  }
}

如何在不将IPlugin 移动到第三个(例如common)包的情况下解决?

PS。我想如果我从MakePlugin 返回*Plugin,这将与Factory 兼容,但不是!!!

【问题讨论】:

  • 把所有东西放在一个包里。

标签: go package circular-dependency


【解决方案1】:

“如何在不将IPlugin 移动到第三个(例如common)包的情况下解决?”

您至少有两个选择:

  1. 将注册移至第三个(例如main)包。
  2. 让每个插件在被其他包导入时自行注册。

示例 #1

package plugins

type IPlugin interface {
  Register() error
}

type Factory func(x int) IPlugin

var registry []Factory

func Register(ff ...Factory) {
    registry = append(registry, ff...)
}
package main

import (
    "plugins"
    "plugins/plugin1"
)

func init() {
    plugins.Register(plugin1. MakePlugin)
}

func main() {
    // ...
}


示例 #2

package plugins

type IPlugin interface {
  Register() error
}

type Factory func(x int) IPlugin

var registry []Factory

func Register(ff ...Factory) {
    registry = append(registry, ff...)
}
package plugin1

import "plugins" // required for IPlugin

func init() {
    plugins.Register(MakePlugin)
}

type Plugin struct {
  x int
}

func MakePlugin(x int) plugins.IPlugin {
  return &Plugin{
    x: x,
  }
}
package main

import (
    "plugins"
    _ "plugins/plugin1" // will execute init() i.e. register
)

func main() {
    // ...
}

【讨论】:

    【解决方案2】:

    尝试将接口与其实现分离到抽象的外部包。然后,根据Dependency injectionAdapter pattern 范式依赖它们。

    【讨论】:

      猜你喜欢
      • 2022-09-22
      • 1970-01-01
      • 2012-03-15
      • 2016-09-21
      • 1970-01-01
      • 1970-01-01
      • 2020-11-12
      相关资源
      最近更新 更多