假设我有一个名为foo
的泛型结构体,我用它创建了两个对象,我可以使用reflect.TypeOf()
确定每个对象的具体类型,如下所示:
package main
import (
"fmt"
"reflect"
)
type foo[T any] struct {
data T
}
func main() {
a := foo[string]{"cheese"}
b := foo[int]{42}
fmt.Println(reflect.TypeOf(a))
fmt.Println(reflect.TypeOf(b))
}
// main.foo[string]
// main.foo[int]
我感兴趣的是只确定这些对象的泛型类型(即foo
),而不是具体类型(即foo[string]
和foo[int]
)。这是可能的,还是需要手动从这些字符串中提取泛型类型(例如,使用regex)?
编辑
正则表达式可能如下所示:
func GetGenericType(x any) string {
// Get type as a string
s := reflect.TypeOf(x).String()
// Regex to run
r := regexp.MustCompile(`\.(.*)\[`)
// Return capture
return r.FindStringSubmatch(s)[1]
}
fmt.Println(GetGenericType(a))
fmt.Println(GetGenericType(b))
// foo
// foo
我也看过this question,但这没有回答这个问题,因为它给出了 * 具体 * 类型(即main.foo[string]
),而不是泛型类型(即foo
)。
1条答案
按热度按时间ddrv8njm1#
反射看不到“基”泛型类型的名称,因为在运行时该基类型不存在。
Go语言规范中的相关段落是示例化:
示例化类型会产生新的非泛型命名类型;示例化函数产生新的非泛型函数。
所以当你写:
该类型的名称正好是
foo[int]
。值得注意的是,没有类型参数列表的 identifier
foo
在编译时是相关的,因为它阻止了你在同一个包中重新声明它。类型定义:类型定义创建一个与给定类型具有相同底层类型和操作的新的不同类型,并将标识符(类型名)绑定到它。
但是如上所定义的示例化导致不同于
foo
的新命名类型;在运行时,当您可以使用反射时,您只处理示例化。总之,我认为使用regex的解决方案是可以接受的,除非向stdlib添加一些辅助函数(如果有的话)。
请记住
Type.String()
和Type.Name()
之间的区别:任何类型都可以有一个字符串表示,但是只有命名类型才有一个名称。(很明显,对吗?)例如,如果你写:那么
b
的类型是*foo[int]
,它是匿名复合类型,并且Name()
返回空字符串。