Take function in argument with empty return type

I would like to understand why the code snippet below does not compile. How can Go accept a function as an argument to a function that can have any type of return value?

package main func main() { test(a) // Error: cannot use a (type func() string) as type func() interface {} in argument to test test(b) // Error: cannot use b (type func() int) as type func() interface {} in argument to test } func a() string { return "hello" } func b() int { return 1 } func test(x func() interface{}) { // some code... v := x() // some more code.... } 

Play: https://play.golang.org/p/CqbuEZGy12

My solution is based on Volker answer:

 package main import ( "fmt" ) func main() { // Wrap function a and b with an anonymous function // that has an empty interface return type. With this // anonymous function, the call signature of test // can be satisfied without needing to modify the return // type of function a and b. test(func() interface{} { return a() }) test(func() interface{} { return b() }) } func a() string { return "hello" } func b() int { return 1 } func test(x func() interface{}) { v := x() fmt.Println(v) } 

Play: https://play.golang.org/p/waOGBZZwN7

+8
source share
2 answers

You are faced with a very common misconception for newcomers to Go: an empty interface interface{} does not mean "any type". This is actually not the case. Go is statically typed. The empty interface {} is the actual (strongly typed type), for example, for example. string or struct{Foo int} or interface{Explode() bool} .

This means that if something is of type interface{} , it is of this type, not "any type."

Your function

 func test(x func() interface{}) 

accepts one parameter. This parameter is (a function without parameters) that returns a specific type, type interface{} . You can pass any function to test that matches this signature: "There are no parameters and return interface{} ". None of your functions a and b match this signature.

As stated above: interface {} not a magic abbreviation for "any", it is a separate static type.

You have to change, for example. a:

 func a() interface{} { return "hello" } 

Now this may look strange when you return a string that is not of type interface{} . This works because any type is assigned to variables of type interface{} (since each type has at least no methods :-).

+12
source

As a specification, Go indicates:

Function type denotes a set of all functions with the same parameter and result types

In your case, your result types are different ( string vs interface{} )

To be able to get a function with any type of result, test should be defined as:

 func text(x interface{}) { ... } 

and then you have to use flip package to call the function stored in x .

Edit

Such a test function would look like this:

 func test(x interface{}) { v := reflect.ValueOf(x) if v.Kind() != reflect.Func { panic("Test requires a function") } t := v.Type() if t.NumIn() != 0 && t.NumOut() != 1 { panic("Function type must have no input parameters and a single return value") } values := v.Call(nil) val := values[0].Interface() // some more code.. } 

Playground: https://play.golang.org/p/trC2lOSLNE

+2
source

All Articles