gitee.com/quant1x/engine@v1.8.4/labs/reflect.go (about)

     1  package labs
     2  
     3  import (
     4  	"fmt"
     5  	"gitee.com/quant1x/engine/factors"
     6  	"reflect"
     7  	"strings"
     8  	"sync"
     9  	"unsafe"
    10  )
    11  
    12  //go:linkname typelinks2 reflect.typelinks
    13  func typelinks2() (sections []unsafe.Pointer, offset [][]int32)
    14  
    15  //go:linkname resolveTypeOff reflect.resolveTypeOff
    16  func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer
    17  
    18  var (
    19  	typeOnce sync.Once
    20  	types    = map[string]reflect.Type{}
    21  	packages = map[string]map[string]reflect.Type{}
    22  )
    23  
    24  type emptyInterface struct {
    25  	typ  unsafe.Pointer
    26  	word unsafe.Pointer
    27  }
    28  
    29  func loadGoTypes() {
    30  	fia := reflect.TypeOf((*factors.Feature)(nil)).Elem()
    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[typeString] = loadedType
    46  				pkgPath := loadedType.PkgPath()
    47  				typeName := loadedType.Name()
    48  				//typeString := loadedType.String()
    49  				//fmt.Println(pkgPath, "=>", typeString, "=>", typeName)
    50  				structName := fmt.Sprintf("%s.%s", pkgPath, typeName)
    51  				types[structName] = loadedType
    52  				pkgTypes[loadedType.Name()] = loadedType
    53  				if strings.HasPrefix(pkgPath, "gitee.com/quant1x/engine") {
    54  					//fmt.Println(structName, "==>", loadedType.PkgPath())
    55  					if reflect.PtrTo(loadedType).Implements(fia) {
    56  						fmt.Println("found", pkgPath, "==>", loadedType.String(), "==>", structName)
    57  					}
    58  				}
    59  			}
    60  		}
    61  	}
    62  }
    63  
    64  func lazyInit() {
    65  	loadGoTypes()
    66  }
    67  
    68  func FindImplements(u reflect.Type) (list []reflect.Type) {
    69  	typeOnce.Do(lazyInit)
    70  	for name, t := range types {
    71  		//fmt.Println(name)
    72  		if reflect.PtrTo(t).Implements(u) {
    73  			list = append(list, t)
    74  		}
    75  		_ = name
    76  	}
    77  	return
    78  }