如何在不创建新包的情况下解决循环依赖?

How to solve circular dependency without creating new package?

在 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 到第 3 个(例如 common)包的情况下解决?

PS。我想如果我 return *Plugin 来自 MakePlugin 这将与 Factory 兼容,但它不兼容!!!

“如何在不将 IPlugin 移动到第 3 个(例如 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() {
    // ...
}

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