reflect.Type.String()
only returns the type name, so if the function value has a named type, you'll only see the type name. Note that this will print the function's signature if the function value is a function literal (has an unnamed type):
var myFunc ModuleInitFunc
fmt.Printf("%T\n", myFunc)
fmt.Printf("%T\n", func(i int) error { return nil })
Output (try it on the Go Playground):
main.ModuleInitFunc
func(int) error
If the type is a named type, we have to construct the signature ourselves, but fortunately the reflect.Type
has all the information we need for that.
Type.In()
returns the type of the ith parameter, and similarly Type.Out()
returns the type of the ith result type.
Using those, here's an example implementation that returns the signature of a function value:
func signature(f interface{}) string {
t := reflect.TypeOf(f)
if t.Kind() != reflect.Func {
return "<not a function>"
}
buf := strings.Builder{}
buf.WriteString("func (")
for i := 0; i < t.NumIn(); i++ {
if i > 0 {
buf.WriteString(", ")
}
buf.WriteString(t.In(i).String())
}
buf.WriteString(")")
if numOut := t.NumOut(); numOut > 0 {
if numOut > 1 {
buf.WriteString(" (")
} else {
buf.WriteString(" ")
}
for i := 0; i < t.NumOut(); i++ {
if i > 0 {
buf.WriteString(", ")
}
buf.WriteString(t.Out(i).String())
}
if numOut > 1 {
buf.WriteString(")")
}
}
return buf.String()
}
Testing it:
var myFunc ModuleInitFunc
fmt.Println(signature(func(i int) error { return nil }))
fmt.Println(signature(myFunc))
fmt.Println(signature(time.Now))
fmt.Println(signature(os.Open))
fmt.Println(signature(log.New))
fmt.Println(signature(""))
Output (try it on the Go Playground):
func (int) error
func (int) error
func () time.Time
func (string) (*os.File, error)
func (io.Writer, string, int) *log.Logger
<not a function>
Note that it is not possible to also print the names of the parameters and result types, because that is not stored / accessible. For details, see Is unnamed arguments a thing in Go?