dump.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. package util
  2. import (
  3. "bytes"
  4. "fmt"
  5. "io"
  6. "reflect"
  7. "strings"
  8. )
  9. const (
  10. // MaxFieldLen const
  11. MaxFieldLen = 100
  12. // MaxSliceLen const
  13. MaxSliceLen = 100
  14. tabSpace = " "
  15. )
  16. // Dump value
  17. func Dump(v interface{}) string {
  18. var bb bytes.Buffer
  19. fdump(&bb, 0, 0, "", reflect.ValueOf(v))
  20. return bb.String()
  21. }
  22. // Fdump value
  23. // func Fdump(w io.Writer, v interface{}) {
  24. // fdump(w, 0, 0, "", reflect.ValueOf(v), "", "")
  25. // }
  26. func fdump(w io.Writer, rx int, rd int, tab string, value reflect.Value) {
  27. rx++
  28. if rx > 100 {
  29. fmt.Fprint(w, "/* too many recursive */")
  30. }
  31. if rd > 10 {
  32. fmt.Fprint(w, "/* too deep */")
  33. }
  34. if value.Kind() == reflect.Interface && !value.IsNil() {
  35. elm := value.Elem()
  36. if elm.Kind() == reflect.Ptr && !elm.IsNil() && elm.Elem().Kind() == reflect.Ptr {
  37. value = elm
  38. }
  39. }
  40. if value.Kind() == reflect.Ptr {
  41. value = value.Elem()
  42. }
  43. if value.Kind() == reflect.String {
  44. fmt.Fprintf(w, "\"%s\" /* Type:%s */", value, value.Type().String())
  45. } else if kindIn(value.Kind(), reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64) {
  46. fmt.Fprintf(w, "%+v /* Type:%s */", value, value.Type().String())
  47. } else if kindIn(value.Kind(), reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64) {
  48. fmt.Fprintf(w, "%+v /* Type:%s */", value, value.Type().String())
  49. } else if value.Kind() == reflect.Struct {
  50. ntab := tab + tabSpace
  51. fmt.Fprintf(w, "{")
  52. il := value.NumField()
  53. for i, j := 0, 0; i < il && i < MaxFieldLen; i++ {
  54. tf := value.Type().Field(i)
  55. tag := strings.Split(value.Type().Field(i).Tag.Get("dump"), ",")
  56. if !InStringSlice("ignore", tag...) {
  57. if j > 0 {
  58. fmt.Fprintf(w, ",\n%s\"%s\": ", ntab, tf.Name)
  59. } else {
  60. fmt.Fprintf(w, "\n%s\"%s\": ", ntab, tf.Name)
  61. }
  62. vf := value.Field(i)
  63. fdump(w, rx, rd+1, ntab, vf)
  64. j++
  65. }
  66. }
  67. fmt.Fprintf(w, "\n%s}", tab)
  68. } else if value.Kind() == reflect.Slice {
  69. ntab := tab + tabSpace
  70. fmt.Fprintf(w, "[ /* Type:%s Length:%v */\n%s", value.Type().String(), value.Len(), ntab)
  71. il := value.Len()
  72. for i := 0; i < il && i < MaxSliceLen; i++ {
  73. vi := value.Index(i)
  74. if i > 0 {
  75. fmt.Fprintf(w, ",\n%s/* Index:%v */ ", ntab, i)
  76. } else {
  77. fmt.Fprint(w, "/* Index:0 */ ")
  78. }
  79. fdump(w, rx, rd+1, ntab, vi)
  80. }
  81. if il > MaxSliceLen {
  82. fmt.Fprintf(w, "\n%s/* too many items */", ntab)
  83. }
  84. fmt.Fprintf(w, "\n%s]%s", tab, "")
  85. // } else if value.CanInterface() {
  86. // fmt.Fprintf(w, "%+v \\\\ Type:%s", value.Interface(), value.Type().String())
  87. } else if value.Kind() == reflect.Map {
  88. ntab := tab + tabSpace
  89. fmt.Fprintf(w, "{ /* Type:%s */\n%s", value.Type().String(), ntab)
  90. keys := value.MapKeys()
  91. for k, kv := range keys {
  92. if k > 0 {
  93. fmt.Fprintf(w, ",\n%s\"%v\": ", ntab, kv)
  94. } else {
  95. fmt.Fprintf(w, "\"%v\": ", kv)
  96. }
  97. fdump(w, rx, rd+1, ntab, value.MapIndex(kv))
  98. }
  99. fmt.Fprintf(w, "\n%s}%s", tab, "")
  100. } else {
  101. fmt.Fprintf(w, "undefined /* Type:%s Value:[%v] */", value.Type().String(), value)
  102. }
  103. }
  104. func kindIn(value reflect.Kind, list ...reflect.Kind) bool {
  105. for _, v := range list {
  106. if value == v {
  107. return true
  108. }
  109. }
  110. return false
  111. }