type_map.go 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  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. func init() {
  16. ver := runtime.Version()
  17. if ver == "go1.5" || strings.HasPrefix(ver, "go1.5.") {
  18. loadGo15Types()
  19. } else if ver == "go1.6" || strings.HasPrefix(ver, "go1.6.") {
  20. loadGo15Types()
  21. } else {
  22. loadGo17Types()
  23. }
  24. }
  25. func loadGo15Types() {
  26. var obj interface{} = reflect.TypeOf(0)
  27. typePtrss := typelinks1()
  28. for _, typePtrs := range typePtrss {
  29. for _, typePtr := range typePtrs {
  30. (*emptyInterface)(unsafe.Pointer(&obj)).word = typePtr
  31. typ := obj.(reflect.Type)
  32. if typ.Kind() == reflect.Ptr && typ.Elem().Kind() == reflect.Struct {
  33. types[typ.Elem().String()] = typ.Elem()
  34. }
  35. if typ.Kind() == reflect.Slice && typ.Elem().Kind() == reflect.Ptr &&
  36. typ.Elem().Elem().Kind() == reflect.Struct {
  37. types[typ.Elem().Elem().String()] = typ.Elem().Elem()
  38. }
  39. }
  40. }
  41. }
  42. func loadGo17Types() {
  43. var obj interface{} = reflect.TypeOf(0)
  44. sections, offset := typelinks2()
  45. for i, offs := range offset {
  46. rodata := sections[i]
  47. for _, off := range offs {
  48. (*emptyInterface)(unsafe.Pointer(&obj)).word = resolveTypeOff(unsafe.Pointer(rodata), off)
  49. typ := obj.(reflect.Type)
  50. if typ.Kind() == reflect.Ptr && typ.Elem().Kind() == reflect.Struct {
  51. types[typ.Elem().String()] = typ.Elem()
  52. }
  53. }
  54. }
  55. }
  56. type emptyInterface struct {
  57. typ unsafe.Pointer
  58. word unsafe.Pointer
  59. }
  60. // TypeByName return the type by its name, just like Class.forName in java
  61. func TypeByName(typeName string) Type {
  62. return Type2(types[typeName])
  63. }