【发布时间】:2020-01-16 09:14:28
【问题描述】:
我有一个关于依赖注入的问题。 请考虑以下示例。
例如 selector() 是一个选择某物并保证返回接口的函数
在这个例子中
bar.node.go
type NodeTemplate struct {
Name string
}
// satisfy interface declared in db.foo.go
//but never imports anything from db.foo.go
func (node *NodeTemplate) GetUuidName() string {
if node != nil {
return node.Name
}
return
}
db.foo.go
// interface declared in db.foo.go
type Node interface {
GetUuidName() string
}
选项 A // 所以 selector 接收到 Some 接口的映射并填充映射
func SelectSomething(nodemap map[string]Node, selectFactor string) {
// selection from db and result populate in a map
}
选项 B
另一种模式 SelectSomething 返回一个节点 和它的接口
所以另一个包将依赖于导入节点 这将引入依赖关系。
func SelectSomething(seleconsomething) []*Node {
// do selection and return a slice of SomeInterface
n := &Node{} // here it need to be concret type T
return Node
}
因此,根据我所描述的逻辑,我认为第一种方法更好,但在这种方法中,选择需要进行具体的类型分配才能填充地图。
考虑另一个例子
db.foo.go
type Node interface {
GetUuidName() string
}
func inserter(node *Node) error {
// do some work
node.GetUuidName()
}
对于inserter这种情况,inserter没有外部依赖,inserter只需要接收满足接口的东西。在本地声明接口并消除依赖关系。
但是在选择器示例的情况下,它必须进行内存分配才能返回或填充映射或返回具有具体类型 T 的东西。所以在这两种情况下,它都必须具有内部重新表示。
所以这是我的问题,选择器可以在运行时以某种方式根据接口找出它接收的类型,并实例化该类型的对象并作为接口插入到地图中或返回接口的一部分。 ?
通过这样做,选择器函数将不依赖于它接收到的内容,它只是保证它会实例化相同的对象类型 T 并返回界面。
或者可以选择器返回接口,但我想我必须在 db 包和包 X 之间有一个双向接口,或者动态调度程序需要做一些魔法?
【问题讨论】:
-
我不喜欢重新发明轮子,当谈到依赖注入(从长远来看,恕我直言,这个概念带来的痛苦多于好处),Go has actually a plethora of options。
-
factory pattern 是尝试做这种事情的 Java 程序的主要部分(有第二个接口,可以创建第一个接口类型的对象,并将工厂作为参数传递给
SelectSomething()需要创建新对象),但在我所见的 Go 中并不是特别常见。