英文:
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
移动到第三个(例如common
)包的情况下解决这个问题?
附注:我以为如果我从MakePlugin
返回*Plugin
,它将与Factory
兼容,但事实并非如此!
英文:
In golang want a plugins system with a global registry. Structure can be simplified as follows:
/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,
}
}
How to solve without moving IPlugin
to 3rd (e.g common
) package?
PS. I thought if i return *Plugin
from MakePlugin
this will be compatible with Factory, but its not!!!
答案1
得分: 4
如何在不将IPlugin
移动到第三方(例如common
)包的情况下解决这个问题?
你至少有两个选项:
- 将注册移到第三方包(例如
main
)中。 - 当某个其他包导入插件时,让每个插件自行注册。
示例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" // 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" // 执行init()即注册
)
func main() {
// ...
}
英文:
"How to solve without moving IPlugin
to 3rd (e.g common
) package?"
You have at least two options:
- move the registration to a 3rd (e.g.
main
) package. - have each plugin register itself when imported by some other package.
Example #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() {
// ...
}
Example #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
得分: 1
尝试将接口与其实现分离到外部的抽象包中。然后,根据依赖注入和适配器模式的范例来依赖它们。
英文:
Try to separate the Interfaces from their implementation to external packages that are abstract. Then, depend on them according to the Dependency injection and Adapter pattern paradigms.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论