我的包中有一个结构,上面有耗时的方法,通过工厂函数进行构造也很耗时。因此,在依赖于该其他结构的包中,我希望能够在创建后使用伪造的工厂函数和伪造的结构对其进行测试。由于结构是通过工厂函数构造的,因此我想伪造工厂函数,并在测试期间将替代工厂函数传递给我的结构。
昂贵的包装的一个例子是:
package expensive import "fmt" type myStruct struct{} func (m *myStruct) DoSomething() { fmt.Println("In Do something") } func (m *myStruct) DoSomethingElse() { fmt.Println("In do something else") } // CreateInstance is expensive to call func CreateInstance() *myStruct { return &myStruct{} }
我的主包装使用以下代码:
package main import "play/expensive" func main() { thing := structToConstruct{expensive.CreateInstance} thing.performAction() } type myInterface interface { DoSomething() } type structToConstruct struct { factoryFunction func() myInterface } func (s *structToConstruct) performAction() { instance := s.factoryFunction() instance.DoSomething() }
但是,此代码抱怨以下错误:
。\ main.go:6:不能在字段值中使用昂贵的CreateInstance(func()* expensive.myStruct类型)作为func()myInterface类型
但是, expensive.myStruct 确实* 实现了myInterface接口,所以我不明白为什么Go抱怨此设置的类型安全。
自从@jmaloney指导之后,我意识到我可以像这样在我的主要方法中包装函数:
wrapper := func() myInterface { return expensive.CreateInstance() } thing := structToConstruct{wrapper}
然后可以工作,但是我仍然不太明白为什么当函数期望返回该接口的实例时,尤其是在此修复程序不需要类型声明/转换的情况下,为什么不能使用实现接口的结构,如它只是在调用底层工厂函数。
编辑:从那以后我就遇到过这个提案,以将其添加到语言中。该提案被拒绝:
https://github.com/golang/go/issues/12754
getInstance 需要返回 myInterface
getInstance
myInterface
package main import "fmt" func main() { var function func() myInterface function = getInstance newSomething := function() newSomething.doSomething() } type myInterface interface { doSomething() } type myStruct struct{} func (m *myStruct) doSomething() { fmt.Println("doing something") } func getInstance() myInterface { return &myStruct{} }
操场上的例子
但是,* expensive.myStruct确实实现了myInterface接口,所以我不明白为什么Go抱怨此设置的类型安全。
在那种情况下,您不是在处理Go的接口,而是在处理结构的类型签名。
当您首次使用factoryFunction func() *myFunctionfactoryFunction 声明结构时,现在始终需要匹配声明的签名。
factoryFunction func() *myFunction