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.