在 Go 中,通过reflect包可以获取 struct 的完整限定名(Fully Qualified Name),即完整导入路径.类型名。
核心方法
go
package main import ( "fmt" "reflect" ) // 假设这是你的 struct type User struct { Name string } func main() { u := User{} // 1. 获取 reflect.Type t := reflect.TypeOf(u) // 2. 完整导入路径(如 "main" 或 "github.com/user/project/models") pkgPath := t.PkgPath() // 3. 类型名(如 "User") typeName := t.Name() // 4. 拼接成全限定名 fullName := pkgPath + "." + typeName fmt.Println(fullName) // 输出: main.User }处理指针的情况
如果传入的是指针,需要先解引用:
go
func fullTypeName(v any) string { t := reflect.TypeOf(v) // 如果是指针,取底层元素类型 if t.Kind() == reflect.Ptr { t = t.Elem() } // 如果不是命名类型(如内置类型、匿名 struct),PkgPath 为空 if t.PkgPath() == "" { return t.String() } return t.PkgPath() + "." + t.Name() } type User struct{} var u *User fmt.Println(fullTypeName(u)) // main.User fmt.Println(fullTypeName(42)) // int(内置类型无 PkgPath)实际项目中的封装
go
package main import ( "fmt" "reflect" ) // FullTypeName 返回类型的全限定名:pkgpath.TypeName // 支持指针、切片、map 等,会穿透到最底层的命名类型 func FullTypeName(v any) string { t := reflect.TypeOf(v) return typeFullName(t) } func typeFullName(t reflect.Type) string { switch t.Kind() { case reflect.Ptr, reflect.Slice, reflect.Array, reflect.Chan, reflect.Map: // 递归取元素类型 return typeFullName(t.Elem()) default: if t.PkgPath() == "" { return t.String() // 内置类型 } return t.PkgPath() + "." + t.Name() } } // 测试 type User struct{} type Status int func main() { var u User var s Status var p *User var users []User fmt.Println(FullTypeName(u)) // main.User fmt.Println(FullTypeName(s)) // main.Status fmt.Println(FullTypeName(p)) // main.User fmt.Println(FullTypeName(users)) // main.User(取元素类型) fmt.Println(FullTypeName(42)) // int fmt.Println(FullTypeName("hello")) // string }关键 API 速查
表格
| 方法 | 返回值示例 | 说明 |
|---|---|---|
reflect.TypeOf(v).Name() | "User" | 类型名(不含包) |
reflect.TypeOf(v).PkgPath() | "main"或"github.com/xxx/yyy" | 完整导入路径 |
reflect.TypeOf(v).String() | "main.User" | 包名.类型名(注意:包名 ≠ 导入路径) |
⚠️
String()返回的是包名(package name),不是导入路径。例如导入路径是github.com/google/uuid,包名可能是uuid,此时String()返回uuid.UUID,而PkgPath()返回github.com/google/uuid。
一句话总结
go
t := reflect.TypeOf(v) if t.Kind() == reflect.Ptr { t = t.Elem() } fullName := t.PkgPath() + "." + t.Name() // 完整导入路径 + 类型名