まず、func() (interface{})
は と同じ意味なfunc() interface{}
ので、短縮形を使用します。
タイプの関数を渡すfunc() interface{}
func() interface{}
次のように、渡す関数が type である限り、引数を取る汎用関数を作成できます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)
}
ライブ プレイグラウンドでこのコードを試すことができます。
http://play.golang.org/p/JJeww9zNhE
型の引数として関数を渡すinterface{}
関数を記述doA
しdoB
、具体的に型指定された値を返す場合は、選択した関数を type の引数として渡すことができます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.
}
より簡潔に:
func Generic(w io.Writer, fn interface{}) {
result := reflect.ValueOf(fn).Call([]reflect.Value{})[0].Interface()
json.NewEncoder(w).Encode(result)
}
完全なプログラム:
パッケージメイン
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)
}
ライブプレイグラウンド:
http://play.golang.org/p/9M5Gr2HDRN