type_map.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. package reflect2
  2. import (
  3. "reflect"
  4. "runtime"
  5. "strings"
  6. "unsafe"
  7. )
  8. // typelinks1 for 1.5 ~ 1.6
  9. //go:linkname typelinks1 reflect.typelinks
  10. func typelinks1() [][]unsafe.Pointer
  11. // typelinks2 for 1.7 ~
  12. //go:linkname typelinks2 reflect.typelinks
  13. func typelinks2() (sections []unsafe.Pointer, offset [][]int32)
  14. var types = map[string]reflect.Type{}
  15. var packages = map[string]map[string]reflect.Type{}
  16. func init() {
  17. ver := runtime.Version()
  18. if ver == "go1.5" || strings.HasPrefix(ver, "go1.5.") {
  19. loadGo15Types()
  20. } else if ver == "go1.6" || strings.HasPrefix(ver, "go1.6.") {
  21. loadGo15Types()
  22. } else {
  23. loadGo17Types()
  24. }
  25. }
  26. func loadGo15Types() {
  27. var obj interface{} = reflect.TypeOf(0)
  28. typePtrss := typelinks1()
  29. for _, typePtrs := range typePtrss {
  30. for _, typePtr := range typePtrs {
  31. (*emptyInterface)(unsafe.Pointer(&obj)).word = typePtr
  32. typ := obj.(reflect.Type)
  33. if typ.Kind() == reflect.Ptr && typ.Elem().Kind() == reflect.Struct {
  34. loadedType := typ.Elem()
  35. pkgTypes := packages[loadedType.PkgPath()]
  36. if pkgTypes == nil {
  37. pkgTypes = map[string]reflect.Type{}
  38. packages[loadedType.PkgPath()] = pkgTypes
  39. }
  40. types[loadedType.String()] = loadedType
  41. pkgTypes[loadedType.Name()] = loadedType
  42. }
  43. if typ.Kind() == reflect.Slice && typ.Elem().Kind() == reflect.Ptr &&
  44. typ.Elem().Elem().Kind() == reflect.Struct {
  45. loadedType := typ.Elem().Elem()
  46. pkgTypes := packages[loadedType.PkgPath()]
  47. if pkgTypes == nil {
  48. pkgTypes = map[string]reflect.Type{}
  49. packages[loadedType.PkgPath()] = pkgTypes
  50. }
  51. types[loadedType.String()] = loadedType
  52. pkgTypes[loadedType.Name()] = loadedType
  53. }
  54. }
  55. }
  56. }
  57. func loadGo17Types() {
  58. var obj interface{} = reflect.TypeOf(0)
  59. sections, offset := typelinks2()
  60. for i, offs := range offset {
  61. rodata := sections[i]
  62. for _, off := range offs {
  63. (*emptyInterface)(unsafe.Pointer(&obj)).word = resolveTypeOff(unsafe.Pointer(rodata), off)
  64. typ := obj.(reflect.Type)
  65. if typ.Kind() == reflect.Ptr && typ.Elem().Kind() == reflect.Struct {
  66. loadedType := typ.Elem()
  67. pkgTypes := packages[loadedType.PkgPath()]
  68. if pkgTypes == nil {
  69. pkgTypes = map[string]reflect.Type{}
  70. packages[loadedType.PkgPath()] = pkgTypes
  71. }
  72. types[loadedType.String()] = loadedType
  73. pkgTypes[loadedType.Name()] = loadedType
  74. }
  75. }
  76. }
  77. }
  78. type emptyInterface struct {
  79. typ unsafe.Pointer
  80. word unsafe.Pointer
  81. }
  82. // TypeByName return the type by its name, just like Class.forName in java
  83. func TypeByName(typeName string) Type {
  84. return Type2(types[typeName])
  85. }
  86. // TypeByPackageName return the type by its package and name
  87. func TypeByPackageName(pkgPath string, name string) Type {
  88. pkgTypes := packages[pkgPath]
  89. if pkgTypes == nil {
  90. return nil
  91. }
  92. return Type2(pkgTypes[name])
  93. }