Im trying to define a couple of interface to refactor some code and I'm getting a problem where Go is not letting me assign functions to variables. This is the set up
main.go
type Gettable interface {
Get() int64
}
type MyFunction func(int64) (Gettable, error)
func main() {
var f MyFunction
f = sub.TestFn2
a, _ := f(1)
fmt.Println(a)
}
main/sub
package sub
type MyStruct struct {
Val int64
}
func (v MyStruct) Get() int64 {
return v.Val
}
func TestFn2(a int64) (MyStruct, error) {
return MyStruct{a}, nil
}
I'm trying to define a generic function type, and in the sub package create the concrete functions
and ideally i want to store the functions in a map and call them with something like
FnMap["fnName"]()
I'm not there yet,
im getting an error saying
/topics.go:27:4: cannot use sub.TestFn2 (type func(int64) (sub.MyStruct, error)) as type MyFunction in assignment
but MyStruct
clearly implements the interface Gettable
This error occurs because of signature don't match. You code shared is:
//shared code
//---------------------------------------------
type Gettable interface {
Get() int64
}
type MyFunction func(int64) (Gettable, error)
So you need replace MyStruct by Gettable.
//main/sub
//---------------------------------------------
type MyStruct struct {
Val int64
}
func (v MyStruct) Get() int64 {
return v.Val
}
//this signature of TestFn2 is different of MyStruct
//-[TestFn2] func (a int64) (MyStruct, error)
//-[MyFunction] func(int64) (Gettable, error)
func TestFn2(a int64) (Gettable, error) {//<-- replace by Gettable here
return MyStruct{a}, nil
}
Running your code:
//main.go
//---------------------------------------------
func main() {
var f MyFunction
f = TestFn2
a, _ := f(1)
fmt.Println(a)
}
Result is:
{1}
See in playground: https://play.golang.org/p/sRsXix8E_83
As per the Go's assignability rules a function f
is assignable to a variable v
only if the variable's type T
exactly matches the f
's signature.
The ability to assign a more specific type in some other languages called "covariance", and Go's type system does not have it.