Go 函数类型返回接口实现的结构
考虑一个场景,其中包含一个包含耗时方法和工厂的包中的结构功能。为了有效地测试这个结构,最好在创建后同时使用一个假工厂函数和一个假结构。
以下代码举例说明了这一点:
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: cannot use expensive.CreateInstance (type func() *expensive.myStruct) as type func() myInterface in field value
尽管 *expense.myStruct 实现了 myInterface,Go 仍然抱怨类型安全。
根据 Go 团队的说法,这种行为是故意的:
Having a function type in a struct field that returns the underlying concrete type would violate a core principle of interfaces. That principle is that the concrete type can be replaced by any other implementation of the interface type. If the receiver type of a function were the underlying concrete type, the behavior of the function would change if called via an interface.
解决方案是包装工厂函数:
wrapper := func() myInterface { return expensive.CreateInstance() } thing := structToConstruct{wrapper}
这个包装器遵循 myInterface 并且代码可以编译。
以上是Go 函数类型返回结构如何用于接口实现?的详细内容。更多信息请关注PHP中文网其他相关文章!