Examining the signature of function assigned to an interface{} variable using reflection

StackOverflow https://stackoverflow.com/questions/22309203

  •  12-06-2023
  •  | 
  •  

Pergunta

I'm trying the build a function that's look like:

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
}

Is it possible to extract the slice of input and output parameters types as []reflect.Type of the function f ?

Foi útil?

Solução

You can use reflect.Type.In(int) and reflect.Type.Out(int), there are corresponding methods called NumIn() int and NumOut() int that give you the number of inputs/outputs.

However, keep in mind a few caveats:

  1. To correctly extract the function for an arbitrary signature, you'll need an infinite number of cases. You'll have to switch over every single In and Out in turn to correctly get the type to extract.
  2. You can't dynamically create a function anyway. There's no FuncOf method to go with SliceOf, MapOf, etc. You'll have to hand code the curried versions anyway.
  3. Using reflection to emulate generics is generally considered a Bad Idea™.

If you absolutely have to do something like this, I'd heavily recommend making an interface and having each implementation do the currying itself, rather than trying to hack it "generically" for all cases, which will never work as of Go 1.2.1.

Outras dicas

Go 1.5 will add a function that could help here. (review 1996, commit e1c1fa2 by Dave (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

The test cases include this intriguing code:

v := MakeFunc(FuncOf([]Type{TypeOf(K(""))}, []Type{TypeOf(V(0))}, false), fn)
outs := v.Call([]Value{ValueOf(K("gopher"))})
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top