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: