11 // typelinks1 for 1.5 ~ 1.6
12 //go:linkname typelinks1 reflect.typelinks
13 func typelinks1() [][]unsafe.Pointer
15 // typelinks2 for 1.7 ~
16 //go:linkname typelinks2 reflect.typelinks
17 func typelinks2() (sections []unsafe.Pointer, offset [][]int32)
19 // initOnce guards initialization of types and packages
20 var initOnce sync.Once
22 var types map[string]reflect.Type
23 var packages map[string]map[string]reflect.Type
25 // discoverTypes initializes types and packages
26 func discoverTypes() {
27 types = make(map[string]reflect.Type)
28 packages = make(map[string]map[string]reflect.Type)
30 ver := runtime.Version()
31 if ver == "go1.5" || strings.HasPrefix(ver, "go1.5.") {
33 } else if ver == "go1.6" || strings.HasPrefix(ver, "go1.6.") {
40 func loadGo15Types() {
41 var obj interface{} = reflect.TypeOf(0)
42 typePtrss := typelinks1()
43 for _, typePtrs := range typePtrss {
44 for _, typePtr := range typePtrs {
45 (*emptyInterface)(unsafe.Pointer(&obj)).word = typePtr
46 typ := obj.(reflect.Type)
47 if typ.Kind() == reflect.Ptr && typ.Elem().Kind() == reflect.Struct {
48 loadedType := typ.Elem()
49 pkgTypes := packages[loadedType.PkgPath()]
51 pkgTypes = map[string]reflect.Type{}
52 packages[loadedType.PkgPath()] = pkgTypes
54 types[loadedType.String()] = loadedType
55 pkgTypes[loadedType.Name()] = loadedType
57 if typ.Kind() == reflect.Slice && typ.Elem().Kind() == reflect.Ptr &&
58 typ.Elem().Elem().Kind() == reflect.Struct {
59 loadedType := typ.Elem().Elem()
60 pkgTypes := packages[loadedType.PkgPath()]
62 pkgTypes = map[string]reflect.Type{}
63 packages[loadedType.PkgPath()] = pkgTypes
65 types[loadedType.String()] = loadedType
66 pkgTypes[loadedType.Name()] = loadedType
72 func loadGo17Types() {
73 var obj interface{} = reflect.TypeOf(0)
74 sections, offset := typelinks2()
75 for i, offs := range offset {
77 for _, off := range offs {
78 (*emptyInterface)(unsafe.Pointer(&obj)).word = resolveTypeOff(unsafe.Pointer(rodata), off)
79 typ := obj.(reflect.Type)
80 if typ.Kind() == reflect.Ptr && typ.Elem().Kind() == reflect.Struct {
81 loadedType := typ.Elem()
82 pkgTypes := packages[loadedType.PkgPath()]
84 pkgTypes = map[string]reflect.Type{}
85 packages[loadedType.PkgPath()] = pkgTypes
87 types[loadedType.String()] = loadedType
88 pkgTypes[loadedType.Name()] = loadedType
94 type emptyInterface struct {
99 // TypeByName return the type by its name, just like Class.forName in java
100 func TypeByName(typeName string) Type {
101 initOnce.Do(discoverTypes)
102 return Type2(types[typeName])
105 // TypeByPackageName return the type by its package and name
106 func TypeByPackageName(pkgPath string, name string) Type {
107 initOnce.Do(discoverTypes)
108 pkgTypes := packages[pkgPath]
112 return Type2(pkgTypes[name])