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  }