string.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. // Package null contains SQL types that consider zero input and null input as separate values,
  2. // with convenient support for JSON and text marshaling.
  3. // Types in this package will always encode to their null value if null.
  4. // Use the zero subpackage if you want zero values and null to be treated the same.
  5. package null
  6. import (
  7. "database/sql"
  8. "encoding/json"
  9. "fmt"
  10. "math/rand"
  11. "reflect"
  12. "github.com/2637309949/dolphin/packages/uuid"
  13. )
  14. // String is a nullable string. It supports SQL and JSON serialization.
  15. // It will marshal to null if null. Blank string input will be considered null.
  16. type String struct {
  17. sql.NullString
  18. }
  19. // StringFrom creates a new String that will never be blank.
  20. func StringFrom(s string) String {
  21. return NewString(s, true)
  22. }
  23. // StringFromRandom creates a new random String that will never be blank.
  24. func StringFromRandom(n int) String {
  25. var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
  26. b := make([]rune, n)
  27. for i := range b {
  28. b[i] = letters[rand.Intn(len(letters))]
  29. }
  30. return NewString(string(b), true)
  31. }
  32. // StringFromUUID creates a new String that will never be blank.
  33. func StringFromUUID() String {
  34. return NewString(uuid.MustString(), true)
  35. }
  36. // StringFromPtr creates a new String that be null if s is nil.
  37. func StringFromPtr(s *string) String {
  38. if s == nil {
  39. return NewString("", false)
  40. }
  41. return NewString(*s, true)
  42. }
  43. // ValueOrZero returns the inner value if valid, otherwise zero.
  44. func (s String) ValueOrZero() string {
  45. if !s.Valid {
  46. return ""
  47. }
  48. return s.String
  49. }
  50. // NewString creates a new String
  51. func NewString(s string, valid bool) String {
  52. return String{
  53. NullString: sql.NullString{
  54. String: s,
  55. Valid: valid,
  56. },
  57. }
  58. }
  59. // UnmarshalJSON implements json.Unmarshaler.
  60. // It supports string and null input. Blank string input does not produce a null String.
  61. // It also supports unmarshalling a sql.NullString.
  62. func (s *String) UnmarshalJSON(data []byte) error {
  63. var err error
  64. var v interface{}
  65. if err = json.Unmarshal(data, &v); err != nil {
  66. return err
  67. }
  68. switch x := v.(type) {
  69. case string:
  70. s.String = x
  71. case map[string]interface{}:
  72. err = json.Unmarshal(data, &s.NullString)
  73. case nil:
  74. s.Valid = false
  75. return nil
  76. default:
  77. err = fmt.Errorf("json: cannot unmarshal %v into Go value of type null.String", reflect.TypeOf(v).Name())
  78. }
  79. s.Valid = err == nil
  80. return err
  81. }
  82. // MarshalJSON implements json.Marshaler.
  83. // It will encode null if this String is null.
  84. func (s String) MarshalJSON() ([]byte, error) {
  85. if !s.Valid {
  86. return []byte("null"), nil
  87. }
  88. return json.Marshal(s.String)
  89. }
  90. // MarshalText implements encoding.TextMarshaler.
  91. // It will encode a blank string when this String is null.
  92. func (s String) MarshalText() ([]byte, error) {
  93. if !s.Valid {
  94. return []byte{}, nil
  95. }
  96. return []byte(s.String), nil
  97. }
  98. // UnmarshalText implements encoding.TextUnmarshaler.
  99. // It will unmarshal to a null String if the input is a blank string.
  100. func (s *String) UnmarshalText(text []byte) error {
  101. s.String = string(text)
  102. s.Valid = s.String != ""
  103. return nil
  104. }
  105. // SetValid changes this String's value and also sets it to be non-null.
  106. func (s *String) SetValid(v string) {
  107. s.String = v
  108. s.Valid = true
  109. }
  110. // Ptr returns a pointer to this String's value, or a nil pointer if this String is null.
  111. func (s String) Ptr() *string {
  112. if !s.Valid {
  113. return nil
  114. }
  115. return &s.String
  116. }
  117. // IsZero returns true for null strings, for potential future omitempty support.
  118. func (s String) IsZero() bool {
  119. return !s.Valid
  120. }