在Go语言中打印类型参数名称。

huangapple go评论64阅读模式
英文:

Print type parameter name in Go

问题

如果我在Golang中编写一个通用函数,我可以像这样打印函数的任一参数的类型,这可以提供一些关于类型参数的见解:

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

然而,如果我修改函数以接受一个切片:

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

这将不会打印我希望的结果,因为调用foo[int]将意味着args的类型为[]int,而我想打印的是int。我可以修改它以打印args[0],但这意味着我还必须检查args为空的情况,在这种情况下,我无法获取args的类型。我也可以使用反射来获取类型,但由于它是一个通用函数,我应该在编译时就知道这一点。

有没有办法在编译时获取T的名称,而不必打印任何参数的类型或通过反射来实现?

英文:

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?

答案1

得分: 10

在编译时打印类型名称是不可能的。fmtreflect 函数(fmt 使用的函数)都是运行时操作。你可能能够通过静态分析找出某个表达式的类型,但这与运行时打印无关。

不管怎样,在运行时,如果类型参数列表捕获了复合类型(包括可变参数切片)的基本类型,你可以通过声明一个新变量来简单地打印它。特别是使用 *new(T) 这个习惯用法可以在一行代码中完成:

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

调用 foo(1,2,3) 将得到字符串:

"[1 2 3] are of type int"

是的,编译器足够聪明,知道 *new(T) 不会逃逸到堆上。

英文:

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"

<hr>

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

答案2

得分: 3

在编译时,是否有一种方法可以获取T的名称,而无需打印任何参数的类型或使用反射?

没有。

你需要使用反射来实现这个。

英文:

> 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?

No

You need reflection for this.

huangapple
  • 本文由 发表于 2022年6月14日 09:55:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/72610728.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定