| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970 |
- // +build !gccgo
- package reflect2
- import (
- "reflect"
- "sync"
- "unsafe"
- )
- // typelinks2 for 1.7 ~
- //go:linkname typelinks2 reflect.typelinks
- func typelinks2() (sections []unsafe.Pointer, offset [][]int32)
- // initOnce guards initialization of types and packages
- var initOnce sync.Once
- var types map[string]reflect.Type
- var packages map[string]map[string]reflect.Type
- // discoverTypes initializes types and packages
- func discoverTypes() {
- types = make(map[string]reflect.Type)
- packages = make(map[string]map[string]reflect.Type)
- loadGoTypes()
- }
- func loadGoTypes() {
- var obj interface{} = reflect.TypeOf(0)
- sections, offset := typelinks2()
- for i, offs := range offset {
- rodata := sections[i]
- for _, off := range offs {
- (*emptyInterface)(unsafe.Pointer(&obj)).word = resolveTypeOff(unsafe.Pointer(rodata), off)
- typ := obj.(reflect.Type)
- if typ.Kind() == reflect.Ptr && typ.Elem().Kind() == reflect.Struct {
- loadedType := typ.Elem()
- pkgTypes := packages[loadedType.PkgPath()]
- if pkgTypes == nil {
- pkgTypes = map[string]reflect.Type{}
- packages[loadedType.PkgPath()] = pkgTypes
- }
- types[loadedType.String()] = loadedType
- pkgTypes[loadedType.Name()] = loadedType
- }
- }
- }
- }
- type emptyInterface struct {
- typ unsafe.Pointer
- word unsafe.Pointer
- }
- // TypeByName return the type by its name, just like Class.forName in java
- func TypeByName(typeName string) Type {
- initOnce.Do(discoverTypes)
- return Type2(types[typeName])
- }
- // TypeByPackageName return the type by its package and name
- func TypeByPackageName(pkgPath string, name string) Type {
- initOnce.Do(discoverTypes)
- pkgTypes := packages[pkgPath]
- if pkgTypes == nil {
- return nil
- }
- return Type2(pkgTypes[name])
- }
|