First, let me remark that func() (interface{})
means the same thing as func() interface{}
, so I'll use the shorter form.
Passing a function of type func() interface{}
You can write a generic function that takes a func() interface{}
argument as long as the function that you pass to it has type func() interface{}
, like this:
type A struct {
Name string
Value int
}
type B struct {
Name1 string
Name2 string
Value float64
}
func doA() interface{} {
return &A{"Cats", 10}
}
func doB() interface{} {
return &B{"Cats", "Dogs", 10.0}
}
func Generic(w io.Writer, fn func() interface{}) {
result := fn()
json.NewEncoder(w).Encode(result)
}
You can try out this code in a live playground:
http://play.golang.org/p/JJeww9zNhE
Passing a function as an argument of type interface{}
If you want to write functions doA
and doB
that return concretely typed values, you can pass the chosen function as an argument of type interface{}
. Then you can use the reflect
package to make a func() interface{}
at run-time:
func Generic(w io.Writer, f interface{}) {
fnValue := reflect.ValueOf(f) // Make a concrete value.
arguments := []reflect.Value{} // Make an empty argument list.
fnResults := fnValue.Call(arguments) // Assume we have a function. Call it.
result := fnResults[0].Interface() // Get the first result as interface{}.
json.NewEncoder(w).Encode(result) // JSON-encode the result.
}
More concisely:
func Generic(w io.Writer, fn interface{}) {
result := reflect.ValueOf(fn).Call([]reflect.Value{})[0].Interface()
json.NewEncoder(w).Encode(result)
}
Complete program:
package main
import (
"encoding/json"
"io"
"os"
"reflect"
)
type A struct {
Name string
Value int
}
type B struct {
Name1 string
Name2 string
Value float64
}
func doA() *A {
return &A{"Cats", 10}
}
func doB() *B {
return &B{"Cats", "Dogs", 10.0}
}
func Generic(w io.Writer, fn interface{}) {
result := reflect.ValueOf(fn).Call([]reflect.Value{})[0].Interface()
json.NewEncoder(w).Encode(result)
}
func main() {
Generic(os.Stdout, doA)
Generic(os.Stdout, doB)
}
Live playground:
http://play.golang.org/p/9M5Gr2HDRN
struct B {
vstype B struct {
and missing)
in theGeneric
definition). You should alsogofmt
all Go code in questions (e.g. that would remove the extraneous parentheses you have around the return types that just make it harder to read). Finally, providing a play.golang.org link can be very helpful to both those trying to answer and those readers that want to try/experiment with the issue; e.g. play.golang.org/p/ON15IwPwDy. – Silkaline