github.com/v2pro/plz@v0.0.0-20221028024117-e5f9aec5b631/reflect2/type_map.go (about) 1 package reflect2 2 3 import ( 4 "unsafe" 5 "reflect" 6 "runtime" 7 "strings" 8 ) 9 10 // typelinks1 for 1.5 ~ 1.6 11 //go:linkname typelinks1 reflect.typelinks 12 func typelinks1() [][]unsafe.Pointer 13 14 // typelinks2 for 1.7 ~ 15 //go:linkname typelinks2 reflect.typelinks 16 func typelinks2() (sections []unsafe.Pointer, offset [][]int32) 17 18 var types = map[string]reflect.Type{} 19 20 func init() { 21 ver := runtime.Version() 22 if ver == "go1.5" || strings.HasPrefix(ver, "go1.5.") { 23 loadGo15Types() 24 } else if ver == "go1.6" || strings.HasPrefix(ver, "go1.6.") { 25 loadGo15Types() 26 } else { 27 loadGo17Types() 28 } 29 } 30 31 func loadGo15Types() { 32 var obj interface{} = reflect.TypeOf(0) 33 typePtrss := typelinks1() 34 for _, typePtrs := range typePtrss { 35 for _, typePtr := range typePtrs { 36 (*emptyInterface)(unsafe.Pointer(&obj)).word = typePtr 37 typ := obj.(reflect.Type) 38 if typ.Kind() == reflect.Ptr && typ.Elem().Kind() == reflect.Struct { 39 types[typ.Elem().String()] = typ.Elem() 40 } 41 if typ.Kind() == reflect.Slice && typ.Elem().Kind() == reflect.Ptr && 42 typ.Elem().Elem().Kind() == reflect.Struct { 43 types[typ.Elem().Elem().String()] = typ.Elem().Elem() 44 } 45 } 46 } 47 } 48 49 func loadGo17Types() { 50 var obj interface{} = reflect.TypeOf(0) 51 sections, offset := typelinks2() 52 for i, offs := range offset { 53 rodata := sections[i] 54 for _, off := range offs { 55 (*emptyInterface)(unsafe.Pointer(&obj)).word = resolveTypeOff(unsafe.Pointer(rodata), off) 56 typ := obj.(reflect.Type) 57 if typ.Kind() == reflect.Ptr && typ.Elem().Kind() == reflect.Struct { 58 types[typ.Elem().String()] = typ.Elem() 59 } 60 } 61 } 62 } 63 64 type emptyInterface struct { 65 typ unsafe.Pointer 66 word unsafe.Pointer 67 } 68 69 // TypeByName return the type by its name, just like Class.forName in java 70 func TypeByName(typeName string) Type { 71 return Type2(types[typeName]) 72 }