string_value.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. package awsutil
  2. import (
  3. "bytes"
  4. "fmt"
  5. "io"
  6. "reflect"
  7. "strings"
  8. )
  9. // StringValue returns the string representation of a value.
  10. func StringValue(i interface{}) string {
  11. var buf bytes.Buffer
  12. stringValue(reflect.ValueOf(i), 0, &buf)
  13. return buf.String()
  14. }
  15. // stringValue will recursively walk value v to build a textual
  16. // representation of the value.
  17. func stringValue(v reflect.Value, indent int, buf *bytes.Buffer) {
  18. for v.Kind() == reflect.Ptr {
  19. v = v.Elem()
  20. }
  21. switch v.Kind() {
  22. case reflect.Struct:
  23. strtype := v.Type().String()
  24. if strtype == "time.Time" {
  25. fmt.Fprintf(buf, "%s", v.Interface())
  26. break
  27. } else if strings.HasPrefix(strtype, "io.") {
  28. buf.WriteString("<buffer>")
  29. break
  30. }
  31. buf.WriteString("{\n")
  32. names := []string{}
  33. for i := 0; i < v.Type().NumField(); i++ {
  34. name := v.Type().Field(i).Name
  35. f := v.Field(i)
  36. if name[0:1] == strings.ToLower(name[0:1]) {
  37. continue // ignore unexported fields
  38. }
  39. if (f.Kind() == reflect.Ptr || f.Kind() == reflect.Slice || f.Kind() == reflect.Map) && f.IsNil() {
  40. continue // ignore unset fields
  41. }
  42. names = append(names, name)
  43. }
  44. for i, n := range names {
  45. val := v.FieldByName(n)
  46. buf.WriteString(strings.Repeat(" ", indent+2))
  47. buf.WriteString(n + ": ")
  48. stringValue(val, indent+2, buf)
  49. if i < len(names)-1 {
  50. buf.WriteString(",\n")
  51. }
  52. }
  53. buf.WriteString("\n" + strings.Repeat(" ", indent) + "}")
  54. case reflect.Slice:
  55. nl, id, id2 := "", "", ""
  56. if v.Len() > 3 {
  57. nl, id, id2 = "\n", strings.Repeat(" ", indent), strings.Repeat(" ", indent+2)
  58. }
  59. buf.WriteString("[" + nl)
  60. for i := 0; i < v.Len(); i++ {
  61. buf.WriteString(id2)
  62. stringValue(v.Index(i), indent+2, buf)
  63. if i < v.Len()-1 {
  64. buf.WriteString("," + nl)
  65. }
  66. }
  67. buf.WriteString(nl + id + "]")
  68. case reflect.Map:
  69. buf.WriteString("{\n")
  70. for i, k := range v.MapKeys() {
  71. buf.WriteString(strings.Repeat(" ", indent+2))
  72. buf.WriteString(k.String() + ": ")
  73. stringValue(v.MapIndex(k), indent+2, buf)
  74. if i < v.Len()-1 {
  75. buf.WriteString(",\n")
  76. }
  77. }
  78. buf.WriteString("\n" + strings.Repeat(" ", indent) + "}")
  79. default:
  80. format := "%v"
  81. switch v.Interface().(type) {
  82. case string:
  83. format = "%q"
  84. case io.ReadSeeker, io.Reader:
  85. format = "buffer(%p)"
  86. }
  87. fmt.Fprintf(buf, format, v.Interface())
  88. }
  89. }