Print type parameter name in Go

Issue

If I write a generic function in Golang, I can print the type of either of the arguments to the function like this, which provides some insight into the type parameter:

func foo[T any](a T, b T) string {
    return fmt.Sprintf("%v and %v are of type %T", a, b, a)
}

However, if I modify the function to take a slice instead:

func foo[T any](args ...T) string {
    return fmt.Sprintf("%+v are of type %T", args, args)
}

this will not print what I would prefer as calling foo[int] will mean that args has a type of []int whereas I want to print int. I could modify this to print args[0] instead but that means I also have to check for the case where args is empty and, in that case, I don’t have a way to get the type of args. I could also use reflection to get the type, but since it’s a generic function, I should also know this at compile-time.

Is there a way I can get name of T at compile time without having to print the type of any arguments or through reflection?

Solution

Printing the type name at compile time is not possible. Both fmt and reflect functions (which fmt uses) are run time operations. You might be able to find out the type of some expression with static analysis but again this is orthogonal to run-time printing.

Anyway at run time, if the type parameter list captures the base type of a composite type, including a vararg slice, you can simply print it by declaring a new variable of that type. The idiom *new(T) in particular allows to do it with one-liners:

func foo[T any](args ...T) string {
    return fmt.Sprintf("%+v are of type %T", args, *new(T))
}

Calling that as foo(1,2,3) now gives the string:

"[1 2 3] are of type int"

Yes, the compiler is smart enough to know that *new(T) doesn’t escape to the heap.

Answered By – blackgreen

Answer Checked By – Pedro (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.