doupu1727 2017-02-17 17:07
浏览 119
已采纳

Go函数类型,该函数类型返回与接口一起使用的结构

I have a struct in a package that has time consuming methods on it and is also time consuming to construct via it's factory function. Therefore, in the package that depends on this other struct I would like to be able to test it using both a fake factory function and a fake struct once it has been created. As the struct is constructed via a factory function I would like to fake the factory function and pass an alternative factory function into my struct during testing time.

An example of the expensive package would be:

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

My main package that uses this then looks like this:

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()
}

However, this code complains with the error:

.\main.go:6: cannot use expensive.CreateInstance (type func() *expensive.myStruct) as type func() myInterface in field value

However, *expensive.myStruct does implement the myInterface interface so I do not understand why Go is complaining about the type safety of this setup.

I've since realised after @jmaloney guideance that I could just wrapper my function like this in my main method:

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

and this then works but I still don't really understand why I can't use a struct that implements an interface when a function is expecting an instance of that interface to be returned especially when no type assertion/conversion is necessary on this fix as it is simply just calling the underlying factory function.

EDIT: I've since come across this proposal to add this to the language. The proposal was rejected:

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

  • 写回答

2条回答 默认 最新

  • douweilaton2762 2017-02-17 17:15
    关注

    getInstance needs to return 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

    However, *expensive.myStruct does implement the myInterface interface so I do not understand why Go is complaining about the type safety of this setup.

    In that instance you were not dealing with Go's interfaces you were dealing with the type signature of your struct.

    when you first declared your struct with factoryFunction func() *myFunction factoryFunction now always needs to match the declared signature.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 求螺旋焊缝的图像处理
  • ¥15 blast算法(相关搜索:数据库)
  • ¥15 请问有人会紧聚焦相关的matlab知识嘛?
  • ¥15 网络通信安全解决方案
  • ¥50 yalmip+Gurobi
  • ¥20 win10修改放大文本以及缩放与布局后蓝屏无法正常进入桌面
  • ¥15 itunes恢复数据最后一步发生错误
  • ¥15 关于#windows#的问题:2024年5月15日的win11更新后资源管理器没有地址栏了顶部的地址栏和文件搜索都消失了
  • ¥100 H5网页如何调用微信扫一扫功能?
  • ¥15 讲解电路图,付费求解