github.com/mymmsc/gox@v1.3.33/util/reflect2/type_map.go (about) 1 //// +build !gccgo 2 3 package reflect2 4 5 import ( 6 "reflect" 7 "sync" 8 "unsafe" 9 ) 10 11 // typelinks2 for 1.7 ~ 12 // 13 //go:linkname typelinks2 reflect.typelinks 14 func typelinks2() (sections []unsafe.Pointer, offset [][]int32) 15 16 // initOnce guards initialization of types and packages 17 var initOnce sync.Once 18 19 var types map[string]reflect.Type 20 var packages map[string]map[string]reflect.Type 21 22 // discoverTypes initializes types and packages 23 func discoverTypes() { 24 types = make(map[string]reflect.Type) 25 packages = make(map[string]map[string]reflect.Type) 26 27 loadGoTypes() 28 } 29 30 func loadGoTypes() { 31 var obj interface{} = reflect.TypeOf(0) 32 sections, offset := typelinks2() 33 for i, offs := range offset { 34 rodata := sections[i] 35 for _, off := range offs { 36 (*emptyInterface)(unsafe.Pointer(&obj)).word = resolveTypeOff(unsafe.Pointer(rodata), off) 37 typ := obj.(reflect.Type) 38 if typ.Kind() == reflect.Ptr && typ.Elem().Kind() == reflect.Struct { 39 loadedType := typ.Elem() 40 pkgTypes := packages[loadedType.PkgPath()] 41 if pkgTypes == nil { 42 pkgTypes = map[string]reflect.Type{} 43 packages[loadedType.PkgPath()] = pkgTypes 44 } 45 types[loadedType.String()] = loadedType 46 pkgTypes[loadedType.Name()] = loadedType 47 } 48 } 49 } 50 } 51 52 type emptyInterface struct { 53 typ unsafe.Pointer 54 word unsafe.Pointer 55 } 56 57 // TypeByName return the type by its name, just like Class.forName in java 58 func TypeByName(typeName string) Type { 59 initOnce.Do(discoverTypes) 60 return Type2(types[typeName]) 61 } 62 63 // TypeByPackageName return the type by its package and name 64 func TypeByPackageName(pkgPath string, name string) Type { 65 initOnce.Do(discoverTypes) 66 pkgTypes := packages[pkgPath] 67 if pkgTypes == nil { 68 return nil 69 } 70 return Type2(pkgTypes[name]) 71 }