我有一个使用反射和反射生成的函数。MakeFunc,所以直到运行时我才有返回类型。
在MakeFunc使用的模板函数中,是否有一种方法来确定被模板化的具体函数的返回类型?
本质上,是否有一种方法可以在运行时确定当前执行函数的返回类型?
我知道Out方法:
fn.Type().Out(0)
我可以很容易地找到一个函数的返回类型吗?
但是是否有一种方法可以找到当前正在执行的函数的返回类型(而不是显式传递的函数引用)?
您应该检查fn.Type().Out(0).Kind()
,例如:
func main() {
fnTmpl := func(in []reflect.Value) []reflect.Value {
return []reflect.Value{in[0]}
}
makeFn := func(fptr interface{}) {
fn := reflect.ValueOf(fptr).Elem()
fn.Set(reflect.MakeFunc(fn.Type(), fnTmpl))
}
var nFn func(int) int
makeFn(&nFn)
kind := reflect.TypeOf(nFn).Out(0).Kind()
switch kind {
case reflect.Int:
fmt.Println("int")
}
}
在这种情况下,当前执行的函数的返回类型总是[]reflect。类型(因为这是函数传递给反映的内容)。MakeFunc必须返回)。您真正需要的是反射的返回类型。makeFuncStub函数调用你的函数。
没有办法得到这个(除非对调用堆栈进行一些奇怪的检查),但是您可以创建一个增强版本的MakeFunc,它提供以下信息:
package main
import (
"fmt"
"reflect"
)
// MakeFunc is like reflect.MakeFunc, but fn has an extra argument, retType, which
// is passed the desired return type.
func MakeFunc(typ reflect.Type, fn func(args []reflect.Value, retType reflect.Type) (results []reflect.Value)) reflect.Value {
if n := typ.NumOut(); n != 1 {
panic("wrong number of return values")
}
rt := typ.Out(0)
return reflect.MakeFunc(typ, func(args []reflect.Value) (results []reflect.Value) {
return fn(args, rt)
})
}
func makeReturnOne(fptr interface{}) {
fn := reflect.ValueOf(fptr).Elem()
fn.Set(MakeFunc(fn.Type(), returnOne))
}
func returnOne(args []reflect.Value, retType reflect.Type) []reflect.Value {
ret := reflect.New(retType).Elem()
switch retType.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
ret.SetInt(1)
case reflect.Float32, reflect.Float64:
ret.SetFloat(1.0)
default:
panic("returnOne only supports int and float types")
}
r := ret.Interface()
fmt.Printf("returning %v as %Tn", r, r)
return []reflect.Value{ret}
}
func main() {
var r1f func() float64
var r1i func() int
makeReturnOne(&r1f)
makeReturnOne(&r1i)
fmt.Println(r1f())
fmt.Println(r1i())
}
我可能误解了你想要实现的目标,但为什么不直接接受你要返回的值呢?修改OneOfOne示例如下:
fnTmpl := func(in []reflect.Value) (res []reflect.Value) {
res = []reflect.Value{in[0]}
fmt.Println("Returned:", res[0].Kind())
return res
}
游乐场:http://play.golang.org/p/EujmxyGRrI