reflect.Type.String()
возвращает только имя типа, поэтому, если значение функции имеет именованный тип, вы увидите только имя типа. Обратите внимание, что при этом будет напечатана подпись функции, если значение функции является литералом функции (имеет безымянный тип):
var myFunc ModuleInitFunc
fmt.Printf("%T\n", myFunc)
fmt.Printf("%T\n", func(i int) error { return nil })
Вывод (попробуйте на Go Playground ):
main.ModuleInitFunc
func(int) error
Если тип является именованным типом, мы должны сами создать сигнатуру, но, к счастью, reflect.Type
обладает всей необходимой для этого информацией.
Type.In()
возвращает тип параметра i th и аналогичным образом Type.Out()
возвращает тип типа результата i th .
Используя их, вот пример реализации, которая возвращает сигнатуру значения функции:
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()
}
Тестирование:
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(""))
Вывод (попробуйте на 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>
Обратите внимание, что также невозможно распечатать имена параметров и типов результатов, поскольку они не сохраняются / недоступны. Подробнее см. Являются ли неназванные аргументы вещью в Go?