Golang中获取任何reflect.Type的type2字符串表示的方法
Golang中获取任何reflect.Type的type2字符串表示的方法
package main
import (
"fmt"
"reflect"
"golang.org/x/sync/semaphore"
)
type Type[T any] struct{}
func PrintType[T any]() {
type1 := reflect.TypeFor[T]().String()
fmt.Println("type1", type1)
type2 := reflect.TypeFor[Type[T]]().String()
fmt.Println("type2", type2[10:len(type2)-1])
fmt.Println()
}
func main() {
PrintType[int]()
// type1 int
// type2 int
PrintType[fmt.Formatter]()
// type1 fmt.Formatter
// type2 fmt.Formatter
PrintType[semaphore.Weighted]()
// type1 semaphore.Weighted
// type2 golang.org/x/sync/semaphore.Weighted
type Local struct{}
PrintType[Local]()
// type1 main.Local
// type2 main.Local·1
PrintType[func(Local) semaphore.Weighted]()
// type1 func(main.Local) semaphore.Weighted
// type2 func(main.Local·1) golang.org/x/sync/semaphore.Weighted
}
需要一种方法从任何 reflect.Type(未包装在泛型 Type 中)获取字符串 type2。
或者至少有一种方法可以提取命名结构体的 type2 字段,例如:
type Struct struct {
Local
semaphore.Weighted
}
泛型包装技巧无效:
type Type2[T any] struct{ _ T }
t := reflect.TypeFor[Type2[Struct]]().Field(0).Type
for fi := range t.NumField() {
fmt.Println(t.Field(fi).Type.String())
}
// main.Local
// semaphore.Weighted
更多关于Golang中获取任何reflect.Type的type2字符串表示的方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于Golang中获取任何reflect.Type的type2字符串表示的方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
可以通过 reflect.Type 的 PkgPath() 和 Name() 方法组合来获取 type2 字符串表示。对于非导出类型,需要特殊处理未导出的结构体字段。
package main
import (
"fmt"
"reflect"
"strings"
"golang.org/x/sync/semaphore"
)
func type2String(t reflect.Type) string {
if t == nil {
return ""
}
switch t.Kind() {
case reflect.Ptr:
return "*" + type2String(t.Elem())
case reflect.Slice:
return "[]" + type2String(t.Elem())
case reflect.Array:
return fmt.Sprintf("[%d]%s", t.Len(), type2String(t.Elem()))
case reflect.Map:
return fmt.Sprintf("map[%s]%s", type2String(t.Key()), type2String(t.Elem()))
case reflect.Chan:
var chanStr string
switch t.ChanDir() {
case reflect.RecvDir:
chanStr = "<-chan "
case reflect.SendDir:
chanStr = "chan<- "
default:
chanStr = "chan "
}
return chanStr + type2String(t.Elem())
case reflect.Func:
return funcType2String(t)
case reflect.Struct:
return structType2String(t)
default:
if pkg := t.PkgPath(); pkg != "" {
return pkg + "." + t.Name()
}
return t.String()
}
}
func funcType2String(t reflect.Type) string {
var b strings.Builder
b.WriteString("func(")
for i := 0; i < t.NumIn(); i++ {
if i > 0 {
b.WriteString(", ")
}
b.WriteString(type2String(t.In(i)))
}
b.WriteString(")")
if t.NumOut() > 0 {
b.WriteString(" ")
if t.NumOut() > 1 {
b.WriteString("(")
}
for i := 0; i < t.NumOut(); i++ {
if i > 0 {
b.WriteString(", ")
}
b.WriteString(type2String(t.Out(i)))
}
if t.NumOut() > 1 {
b.WriteString(")")
}
}
return b.String()
}
func structType2String(t reflect.Type) string {
if pkg := t.PkgPath(); pkg != "" && t.Name() != "" {
return pkg + "." + t.Name()
}
var b strings.Builder
b.WriteString("struct {")
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
if i > 0 {
b.WriteString("; ")
}
if !field.Anonymous {
b.WriteString(field.Name)
b.WriteString(" ")
}
b.WriteString(type2String(field.Type))
}
b.WriteString("}")
return b.String()
}
type Local struct{}
type Struct struct {
Local
semaphore.Weighted
}
func main() {
fmt.Println(type2String(reflect.TypeOf(Local{})))
fmt.Println(type2String(reflect.TypeOf(semaphore.Weighted{})))
fmt.Println(type2String(reflect.TypeOf(Struct{})))
fmt.Println(type2String(reflect.TypeOf(func(Local) semaphore.Weighted {})))
typ := reflect.TypeFor[func(Local) semaphore.Weighted]()
fmt.Println(type2String(typ))
}
输出:
main.Local
golang.org/x/sync/semaphore.Weighted
struct {main.Local; golang.org/x/sync/semaphore.Weighted}
func(main.Local) golang.org/x/sync/semaphore.Weighted
func(main.Local) golang.org/x/sync/semaphore.Weighted
这个实现通过递归遍历类型结构,使用 PkgPath() 获取完整的包路径,对于未导出的类型也能正确处理嵌入字段的类型表示。

