13

Given the following Go method:

func (t *T) TMethod(data *testData) (interface{}, *error) {
    ...
}

I want to reflect the name of the parameter (which is data here).

I tried the following, but it returns the structure name (which is testData here):

reflect.ValueOf(T).MethodByName("TMethod").Type.In(0).Elem().Name()

How can I get the name of the parameter?

2
  • You didn't try that code, since it doesn't compile. Commented Jul 13, 2015 at 7:31
  • @ rightfold: I tried it , just added more details. Commented Jul 13, 2015 at 7:41

2 Answers 2

26

There is no way to get the names of the parameters of a method or a function.

The reason for this is because the names are not really important for someone calling a method or a function. What matters is the types of the parameters and their order.

A Function type denotes the set of all functions with the same parameter and result types. The type of 2 functions having the same parameter and result types is identical regardless of the names of the parameters. The following code prints true:

func f1(a int) {}
func f2(b int) {}

fmt.Println(reflect.TypeOf(f1) == reflect.TypeOf(f2))

It is even possible to create a function or method where you don't even give names to the parameters (within a list of parameters or results, the names must either all be present or all be absent). This is valid code:

func NamelessParams(int, string) {
    fmt.Println("NamelessParams called")
}

For details and examples, see Is unnamed arguments a thing in Go?

If you want to create some kind of framework where you call functions passing values to "named" parameters (e.g. mapping incoming API params to Go function/method params), you may use a struct because using the reflect package you can get the named fields (e.g. Value.FieldByName() and Type.FieldByName()), or you may use a map. See this related question: Initialize function fields

Here is a relevant discussion on the golang-nuts mailing list.

Sign up to request clarification or add additional context in comments.

Comments

2

Update 2025: I built a bit of a hack to solve this!

I know this is an old question, but I ran into the same need recently and ended up creating a package to solve it. The standard library still can't do this, but I built dwarfreflect that extracts parameter names using DWARF debug info.

Here's what you can now do:

package main

import (
    "fmt"
    "github.com/matteo-grella/dwarfreflect"
)

func ExampleFunction(name string, age int, active bool) string {
    return fmt.Sprintf("%s (%d years old, active: %v)", name, age, active)
}

func main() {
    fn := dwarfreflect.NewFunction(ExampleFunction)
    
    // Finally! Get the actual parameter names
    names, _ := fn.GetParameterInfo()
    fmt.Println(names) // [name age active]
    
    // Call it with a map instead of positional args
    result := fn.CallWithMap(map[string]any{
        "name":   "Alice",
        "age":    30,
        "active": true,
    })
    fmt.Println(result[0].String()) // Alice (30 years old, active: true)
}

Try it on the playground: https://go.dev/play/p/l-nu7WlIxok

I was working on a Go agent framework where I wanted users to just pass in plain functions and have the system figure out the parameter binding automatically. This reflection gap was exactly what I needed to solve.

How it works: It parses the DWARF debug info that Go embeds in binaries by default. No code generation, no struct tags - just works at runtime.

Limitation: Needs debug info (present by default), won't work with stripped binaries (-ldflags="-s -w").

GitHub issue #12384 has been open since 2015 without an official solution, so I figured the community needed a practical approach. This should be useful for API frameworks, RPC libraries, or anywhere you need semantic function calls instead of positional arguments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.