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  }