struct.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. package gofakeit
  2. import (
  3. "reflect"
  4. )
  5. // Struct fills in exported elements of a struct with random data
  6. // based on the value of `fake` tag of exported elements.
  7. // Use `fake:"skip"` to explicitly skip an element.
  8. // All built-in types are supported, with templating support
  9. // for string types.
  10. func Struct(v interface{}) {
  11. r(reflect.TypeOf(v), reflect.ValueOf(v), "")
  12. }
  13. func r(t reflect.Type, v reflect.Value, template string) {
  14. switch t.Kind() {
  15. case reflect.Ptr:
  16. rPointer(t, v, template)
  17. case reflect.Struct:
  18. rStruct(t, v)
  19. case reflect.String:
  20. rString(template, v)
  21. case reflect.Uint8:
  22. v.SetUint(uint64(Uint8()))
  23. case reflect.Uint16:
  24. v.SetUint(uint64(Uint16()))
  25. case reflect.Uint32:
  26. v.SetUint(uint64(Uint32()))
  27. case reflect.Uint64:
  28. //capped at [0, math.MaxInt64)
  29. v.SetUint(uint64(Uint64()))
  30. case reflect.Int:
  31. v.SetInt(int64(Int64()))
  32. case reflect.Int8:
  33. v.SetInt(int64(Int8()))
  34. case reflect.Int16:
  35. v.SetInt(int64(Int16()))
  36. case reflect.Int32:
  37. v.SetInt(int64(Int32()))
  38. case reflect.Int64:
  39. v.SetInt(int64(Int64()))
  40. case reflect.Float64:
  41. v.SetFloat(Float64())
  42. case reflect.Float32:
  43. v.SetFloat(float64(Float32()))
  44. case reflect.Bool:
  45. v.SetBool(Bool())
  46. }
  47. }
  48. func rString(template string, v reflect.Value) {
  49. if template != "" {
  50. r := Generate(template)
  51. v.SetString(r)
  52. } else {
  53. v.SetString(Generate("???????????????????"))
  54. // we don't have a String(len int) string function!!
  55. }
  56. }
  57. func rStruct(t reflect.Type, v reflect.Value) {
  58. n := t.NumField()
  59. for i := 0; i < n; i++ {
  60. elementT := t.Field(i)
  61. elementV := v.Field(i)
  62. fake := true
  63. t, ok := elementT.Tag.Lookup("fake")
  64. if ok && t == "skip" {
  65. fake = false
  66. }
  67. if fake && elementV.CanSet() {
  68. r(elementT.Type, elementV, t)
  69. }
  70. }
  71. }
  72. func rPointer(t reflect.Type, v reflect.Value, template string) {
  73. elemT := t.Elem()
  74. if v.IsNil() {
  75. nv := reflect.New(elemT)
  76. r(elemT, nv.Elem(), template)
  77. v.Set(nv)
  78. } else {
  79. r(elemT, v.Elem(), template)
  80. }
  81. }