github.com/wfusion/gofusion@v1.1.14/common/utils/inspect/inspect.go (about)

     1  // Inspired by github.com/chenzhuoyu/go-inspect
     2  
     3  package inspect
     4  
     5  import (
     6  	"reflect"
     7  	"runtime"
     8  	"sync"
     9  	"unsafe"
    10  )
    11  
    12  var (
    13  	lock    sync.RWMutex
    14  	structs = make(map[string]reflect.Type)
    15  	funcs   = make(map[string]unsafe.Pointer)
    16  
    17  	supportTypes = map[reflect.Kind]bool{
    18  		reflect.Bool:       true,
    19  		reflect.Int:        true,
    20  		reflect.Int8:       true,
    21  		reflect.Int16:      true,
    22  		reflect.Int32:      true,
    23  		reflect.Int64:      true,
    24  		reflect.Uint:       true,
    25  		reflect.Uint8:      true,
    26  		reflect.Uint16:     true,
    27  		reflect.Uint32:     true,
    28  		reflect.Uint64:     true,
    29  		reflect.Uintptr:    true,
    30  		reflect.Float32:    true,
    31  		reflect.Float64:    true,
    32  		reflect.Complex64:  true,
    33  		reflect.Complex128: true,
    34  		reflect.Array:      true,
    35  		reflect.Chan:       true,
    36  		reflect.Map:        true,
    37  		reflect.Slice:      true,
    38  		reflect.String:     true,
    39  		reflect.Struct:     true,
    40  		reflect.Interface:  true,
    41  	}
    42  )
    43  
    44  // TypeOf find the type by package path and name
    45  func TypeOf(typeName string) reflect.Type {
    46  	lock.RLock()
    47  	defer lock.RUnlock()
    48  	if typ, ok := structs[typeName]; ok {
    49  		return typ
    50  	}
    51  	return nil
    52  }
    53  
    54  // RuntimeTypeOf find the type by package path and name in runtime
    55  func RuntimeTypeOf(typeName string) (r reflect.Type) {
    56  	enumerateTypes(func(typ reflect.Type) bool {
    57  		if typ.PkgPath()+"."+typ.Name() == typeName {
    58  			r = typ
    59  			return false
    60  		}
    61  		return true
    62  	})
    63  	return
    64  }
    65  
    66  // FuncOf find the function entry by package path and name,
    67  // the function should be linked and should not be inlined
    68  func FuncOf(funcName string) unsafe.Pointer {
    69  	lock.RLock()
    70  	defer lock.RUnlock()
    71  	if entry, ok := funcs[funcName]; ok {
    72  		return unsafe.Pointer(&entry)
    73  	}
    74  	return nil
    75  }
    76  
    77  // RuntimeFuncOf find the function entry by package path and name in runtime,
    78  // the function should be linked and should not be inlined
    79  func RuntimeFuncOf(funcName string) (r unsafe.Pointer) {
    80  	enumerateFuncs(func(fn *runtime.Func, addr uintptr) bool {
    81  		if fn.Name() == funcName {
    82  			r = unsafe.Pointer(&addr)
    83  			return false
    84  		}
    85  		return true
    86  	})
    87  	return
    88  }
    89  
    90  func init() {
    91  	lock.Lock()
    92  	defer lock.Unlock()
    93  
    94  	// inspect structs
    95  	enumerateTypes(func(typ reflect.Type) bool {
    96  		pkgName := typ.PkgPath()
    97  		typeName := typ.Name()
    98  		if pkgName != "" && typeName != "" {
    99  			structs[pkgName+"."+typeName] = typ
   100  		}
   101  
   102  		return true
   103  	})
   104  
   105  	// inspect function
   106  	enumerateFuncs(func(fn *runtime.Func, addr uintptr) bool {
   107  		if funcName := fn.Name(); funcName != "" {
   108  			funcs[funcName] = unsafe.Pointer(&addr)
   109  		}
   110  		return true
   111  	})
   112  }