我想知道如何在golang中灵活地注入依赖,就像java spring一样,如果我想更改接口的实例,我只需要更改一些配置文件。
首先我想找一些像 getTypeByName()这样的函数,所以我可以在配置文件中给出一个像“mypkg.structName”这样的结构名称并通过该函数加载该结构,但似乎golang中没有这样的功能。
现在我能想到的最可行的方法是创建一个加载器模型来生成struct register file以加载所有自定义结构。
但我想知道是否有更简单的方法可以做到这一点,是否有一些golang风格的方式来实现这种灵活性?
答案 0 :(得分:3)
我认为您的方法是正确的,因为如果在编译期间未定义类型,则无法实例化该类型。否则,您需要使用plugin
。
我不确定是否更容易,但如果您希望将自定义结构组织在不同的包中,则可以使用与{{1}类似的方法}。
定义一个工厂包,其中包含database/sql
接口和管理已知工厂。此程序包应导出Factory
函数以注册自定义工厂,并Register
函数用于创建给定类型的实例。例如:
New
创建包含自定义结构并实现package factory
import (
"strings"
"sync"
)
type Factory interface {
New(name string) (interface{}, bool)
}
var (
mu sync.RWMutex
factories = make(map[string]Factory)
)
func Register(pkgName string, f Factory) {
mu.Lock()
defer mu.Unlock()
if f == nil {
panic("Factory is nil")
}
if _, exist := factories[pkgName]; exist {
panic("Factory already registered")
}
factories[pkgName] = f
}
func New(typeName string) (interface{}, bool) {
items := strings.Split(typeName, ".")
if len(items) >= 2 {
mu.RLock()
defer mu.RUnlock()
if f, exist := factories[items[0]]; exist {
return f.New(items[1])
}
}
return nil, false
}
接口的包。在初始化期间注册工厂,即Factory
功能,例如
init()
根据需要重复步骤(2)。
最后,在主包中,您可以按如下方式创建实例:
package pkga
import "path/to/your/factory"
type thisFactory struct {
}
type Alpha struct{}
type Beta struct{}
type Gamma struct{}
func (f *thisFactory) New(name string) (interface{}, bool) {
switch name {
case "Alpha":
return &Alpha{}, true
case "Beta":
return &Beta{}, true
case "Gamma":
return &Gamma{}, true
}
return nil, false
}
func init() {
factory.Register("pkga", &thisFactory{})
}
更新:提供了一个工作示例here。