我有一个使用reflection和reflect.MakeFunc生成的函数,所以我直到运行时才真正拥有返回类型。
在MakeFunc正在使用的模板函数中,有没有办法确定被模板化的具体函数的返回类型?
基本上,有没有办法在运行时确定当前正在执行的函数的返回类型?
我知道Out方法:
fn.Type().Out(0)
我能够轻松找到函数的返回类型吗?
但是有没有办法找到当前正在执行的函数的返回类型(而不是显式传递的函数引用)。
答案 0 :(得分:3)
在你谈论的情况下,当前正在执行的函数的返回类型总是[] reflect.Type(因为这是函数传递给reflect.MakeFunc必须返回的)。你真正想要的是调用你的函数的reflect.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 %T\n", 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())
}
答案 1 :(得分:2)
您应该fn.Type().Out(0).Kind()
检查example:
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")
}
}
答案 2 :(得分:1)
我可能误解了你想要实现的目标,但为什么不采取你正在回归的那种价值呢?修改OneOfOne的示例如下:
fnTmpl := func(in []reflect.Value) (res []reflect.Value) {
res = []reflect.Value{in[0]}
fmt.Println("Returned:", res[0].Kind())
return res
}