Alex
Alex

Reputation: 3076

Why typeof(method) does not return reflect.Method instance?

Let's say I have Foo struct with a method defined as follows:

type Foo struct {
    Name string
}

func (f *Foo) Get(a int, b string) (string, error) {
    return f.Name, nil
}

If I write

obj := &Foo{}
t := reflect.TypeOf(obj.Get)

t.Kind() returns reflect.Func and apparently I have no way to access information that Get func I extracted type information from "belongs" to the Foo struct, that is receiver is of Foo type, it is not even surfaced in the in-parameters.

I guess that's intentional and I miss something fundamental about functions that made language authors throw away receiver information for typeof operations applied to method references.

I have two questions:

  1. Am I correct and there is no way to get receiver type in the snippet with TypeOf call above?
  2. What are the alternatives I have if I want to pass reflection information about a method to some code that intends to analyze function and related receiver (that is, in essence a method)?

Trying to answer second question myself and based on what I see in the official documentation, it looks like my only options are to either pass TypeOf(receiver) and TypeOf(receiver.method) or TypeOf(receiver) and the name of the receiver's method.

Upvotes: 2

Views: 535

Answers (1)

icza
icza

Reputation: 417672

As mentioned by mkopriva, what you have is a method value: obj.Get. And the method value is a function whose signature is identical to the method's without the receiver type:

If the expression x has static type T and M is in the method set of type T, x.M is called a method value. The method value x.M is a function value that is callable with the same arguments as a method call of x.M. The expression x is evaluated and saved during the evaluation of the method value; the saved copy is then used as the receiver in any calls, which may be executed later.

If you use a method expression (instead of a method value), the receiver type "shows" up in the parameter list (it's always the first):

fmt.Println(reflect.TypeOf((*Foo).Get))

Outputs (try it on the Go Playground):

func(*main.Foo, int, string) (string, error)

The method expression:

If M is in the method set of type T, T.M is a function that is callable as a regular function with the same arguments as M prefixed by an additional argument that is the receiver of the method.

See related questions:

golang - pass method to function

golang function alias on method receiver

Upvotes: 5

Related Questions