我在一个包中有一个结构,它有耗时的方法,并且通过它的工厂函数构建也很费时。因此,在依赖于这个其他结构的包中,我希望能够在创建后使用伪工厂函数和伪结构来测试它。由于结构是通过工厂函数构造的,我想伪造工厂函数并在测试期间将替代工厂函数传递给我的结构。
昂贵包装的一个例子是:
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:不能使用expensive.CreateInstance(类型为func()* expensive.myStruct)作为字段值类型func()myInterface
但是,* expensive.myStruct 确实实现了myInterface接口,所以我不明白为什么Go会抱怨此设置的类型安全性。
我已经意识到在@jmaloney引导之后我可以在我的main方法中将这个函数包装起来:
wrapper := func() myInterface {
return expensive.CreateInstance()
}
thing := structToConstruct{wrapper}
然后这可行但我仍然不明白为什么我不能使用实现接口的结构,当一个函数期望返回该接口的实例时,尤其是当不需要类型断言/转换时这个修复,因为它只是调用底层工厂函数。
编辑:我已经遇到过这个提议,将其添加到语言中。提案遭到拒绝:
答案 0 :(得分:4)
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() *myFunction
factoryFunction声明你的结构时,现在总是需要匹配声明的签名。
答案 1 :(得分:0)
看看这可能有用,有一个函数返回给定struct的接口。
package main
import "fmt"
func main() {
var instance myInterface
// The return value of the getInstance function can be assigned to a variable
// of type myInterface
instance = getInstance()
var function func(*myStruct) myInterface
// But the function itself can't be assigned to a variable for a function
// that returns a myInterface. You get:
// cannot use getInstance (type func() *myStruct) as type func() myInterface in assignment
function = getMyInstance
r := function(instance.(*myStruct))
r.doSomething()
}
type myInterface interface {
doSomething()
}
type myStruct struct{}
func (m *myStruct) doSomething() {
fmt.Println("Done something")
}
func getInstance() *myStruct {
return &myStruct{}
}
func getMyInstance(myInst *myStruct) myInterface {
return myInst
}
时可用