返回返回与接口

时间:2017-02-17 17:07:10

标签: function 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:不能使用expensive.CreateInstance(类型为func()* expensive.myStruct)作为字段值类型func()myInterface

但是,* expensive.myStruct 确实实现了myInterface接口,所以我不明白为什么Go会抱怨此设置的类型安全性。

我已经意识到在@jmaloney引导之后我可以在我的main方法中将这个函数包装起来:

    wrapper := func() myInterface {
        return expensive.CreateInstance()
    }
    thing := structToConstruct{wrapper}

然后这可行但我仍然不明白为什么我不能使用实现接口的结构,当一个函数期望返回该接口的实例时,尤其是当不需要类型断言/转换时这个修复,因为它只是调用底层工厂函数。

编辑:我已经遇到过这个提议,将其添加到语言中。提案遭到拒绝:

https://github.com/golang/go/issues/12754

2 个答案:

答案 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{}
}

Playground example

  

但是,* 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

}

https://play.golang.org/p/h8iJ0i-Xym

时可用