dump.go 3.7 KB

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