使用反射检查分配给接口{}变量的函数的签名

时间:2014-03-10 19:13:15

标签: reflection go currying

我正在尝试构建 函数,如下所示:

package curry

import (
    "fmt"
    "reflect"
)

// Function
type fn interface{}

// Function parameter
type pr interface{}

// It return the curried function
func It(f fn, p ...pr) (fn, error) {
    // examine the concret type of the function f
    if reflect.ValueOf(f).Kind() == reflect.Func {
    // Get the slice of input and output parameters type 
    } else {
        return nil, fmt.Errorf("%s", "takes a function as a first parameter")
    }
    // _, _ = f, p
    return nil, nil
}

是否可以将输入和输出参数类型的片段提取为函数[]reflect.Type的{​​{1}}?

2 个答案:

答案 0 :(得分:3)

您可以使用reflect.Type.In(int)reflect.Type.Out(int),有相应的方法NumIn() intNumOut() int可以为您提供输入/输出的数量。

但是,请记住一些警告:

  1. 要正确提取任意签名的函数,您需要无数个案例。您必须依次切换每个In和Out才能正确获取要提取的类型。
  2. 无论如何都无法动态创建功能。没有FuncOf方法可以使用SliceOf,MapOf等。无论如何,你必须手动编写咖喱版本。
  3. 使用反射来模拟泛型通常被认为是一个坏主意。
  4. 如果你绝对不得不做这样的事情,我会强烈建议你创建一个界面并让每个实现都自己进行讨论,而不是试图在所有情况下“通用”地破解它,这将永远不会像Go一样1.2.1。

答案 1 :(得分:1)

Go 1.5将添加一个可以帮助的功能。 (review 1996commit e1c1fa2Dave (okdave)

// FuncOf returns the function type with the given argument and result types.
// For example if k represents int and e represents string,
// FuncOf([]Type{k}, []Type{e}, false) represents func(int) string.
//
// The variadic argument controls whether the function is variadic. FuncOf
// panics if the in[len(in)-1] does not represent a slice and variadic is
// true.
func FuncOf(in, out []Type, variadic bool) Type

测试用例包括这个有趣的代码:

v := MakeFunc(FuncOf([]Type{TypeOf(K(""))}, []Type{TypeOf(V(0))}, false), fn)
outs := v.Call([]Value{ValueOf(K("gopher"))})