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!!!
CodePudding user response:
"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() {
// ...
}
CodePudding user response:
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.
