Eri*_*ric 6 go first-class-functions
我正在尝试动态调用返回不同类型的函数struct.
例如,让我们采用以下代码.
struct A {
Name string
Value int
}
struct B {
Name1 string
Name2 string
Value float
}
func doA() (A) {
// some code returning A
}
func doB() (B) {
// some code returning B
}
Run Code Online (Sandbox Code Playgroud)
我想将函数doA或doB作为参数传递给将执行函数和JSON编码结果的泛型函数.如下:
func Generic(w io.Writer, fn func() (interface {}) {
result := fn()
json.NewEncoder(w).Encode(result)
}
Run Code Online (Sandbox Code Playgroud)
但当我这样做时:
Generic(w, doA)
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
cannot use doA (type func() (A)) as type func() (interface {})
Run Code Online (Sandbox Code Playgroud)
有没有办法实现这种动态调用?
首先,让我注意这func() (interface{})意味着同样的事情func() interface{},所以我将使用更短的形式.
func() interface{}func() interface{}只要传递给它的函数具有类型func() interface{},就可以编写一个带参数的泛型函数,如下所示:
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)
}
Run Code Online (Sandbox Code Playgroud)
您可以在实时游乐场中试用此代码:
http://play.golang.org/p/JJeww9zNhE
interface{}如果要编写函数doA并doB返回具体类型的值,则可以将所选函数作为类型的参数传递interface{}.然后你可以使用reflect包做出func() interface{}在运行时:
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.
}
Run Code Online (Sandbox Code Playgroud)
更简洁:
func Generic(w io.Writer, fn interface{}) {
result := reflect.ValueOf(fn).Call([]reflect.Value{})[0].Interface()
json.NewEncoder(w).Encode(result)
}
Run Code Online (Sandbox Code Playgroud)
完整计划:
包主
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)
}
Run Code Online (Sandbox Code Playgroud)
现场操场:
http://play.golang.org/p/9M5Gr2HDRN