float.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. package null
  2. import (
  3. "database/sql"
  4. "encoding/json"
  5. "fmt"
  6. "reflect"
  7. "strconv"
  8. )
  9. const (
  10. nullString = "null"
  11. )
  12. // Float is a nullable float64.
  13. // It does not consider zero values to be null.
  14. // It will decode to null, not zero, if null.
  15. type Float struct {
  16. sql.NullFloat64
  17. }
  18. // NewFloat creates a new Float
  19. func NewFloat(f float64, valid bool) Float {
  20. return Float{
  21. NullFloat64: sql.NullFloat64{
  22. Float64: f,
  23. Valid: valid,
  24. },
  25. }
  26. }
  27. // FloatFrom creates a new Float that will always be valid.
  28. func FloatFrom(f float64) Float {
  29. return NewFloat(f, true)
  30. }
  31. // FloatFromPtr creates a new Float that be null if f is nil.
  32. func FloatFromPtr(f *float64) Float {
  33. if f == nil {
  34. return NewFloat(0, false)
  35. }
  36. return NewFloat(*f, true)
  37. }
  38. // FloatFromString creates a new Float from string f.
  39. // If the string is equal to the value of nullString then the Float will be null.
  40. // An empty string f will return an error.
  41. func FloatFromString(f string, nullString string) (Float, error) {
  42. if f == nullString {
  43. return FloatFromPtr(nil), nil
  44. }
  45. fV, err := strconv.ParseFloat(f, 64)
  46. if err != nil {
  47. return Float{}, err
  48. }
  49. return FloatFrom(fV), nil
  50. }
  51. // UnmarshalJSON implements json.Unmarshaler.
  52. // It supports number and null input.
  53. // 0 will not be considered a null Float.
  54. // It also supports unmarshalling a sql.NullFloat64.
  55. func (f *Float) UnmarshalJSON(data []byte) error {
  56. var err error
  57. var v interface{}
  58. if err = json.Unmarshal(data, &v); err != nil {
  59. return err
  60. }
  61. switch x := v.(type) {
  62. case float64:
  63. f.Float64 = x
  64. case map[string]interface{}:
  65. err = json.Unmarshal(data, &f.NullFloat64)
  66. case nil:
  67. f.Valid = false
  68. return nil
  69. default:
  70. err = fmt.Errorf("json: cannot unmarshal %v into Go value of type null.Float", reflect.TypeOf(v).Name())
  71. }
  72. f.Valid = err == nil
  73. return err
  74. }
  75. // UnmarshalText implements encoding.TextUnmarshaler.
  76. // It will unmarshal to a null Float if the input is a blank or not an integer.
  77. // It will return an error if the input is not an integer, blank, or "null".
  78. func (f *Float) UnmarshalText(text []byte) error {
  79. str := string(text)
  80. if str == "" || str == nullString {
  81. f.Valid = false
  82. return nil
  83. }
  84. var err error
  85. f.Float64, err = strconv.ParseFloat(string(text), 64)
  86. f.Valid = err == nil
  87. return err
  88. }
  89. // MarshalJSON implements json.Marshaler.
  90. // It will encode null if this Float is null.
  91. func (f Float) MarshalJSON() ([]byte, error) {
  92. if !f.Valid {
  93. return []byte(nullString), nil
  94. }
  95. return []byte(strconv.FormatFloat(f.Float64, 'f', -1, 64)), nil
  96. }
  97. // MarshalText implements encoding.TextMarshaler.
  98. // It will encode a blank string if this Float is null.
  99. func (f Float) MarshalText() ([]byte, error) {
  100. if !f.Valid {
  101. return []byte{}, nil
  102. }
  103. return []byte(strconv.FormatFloat(f.Float64, 'f', -1, 64)), nil
  104. }
  105. // MarshalText implements encoding.TextMarshaler.
  106. // It will encode a blank string if this Float is null.
  107. func (f Float) String() string {
  108. if !f.Valid {
  109. return nullString
  110. }
  111. return fmt.Sprintf("%1.3f", f.Float64)
  112. }
  113. // FullString returns float as string in full precision
  114. func (f Float) FullString() string {
  115. if !f.Valid {
  116. return nullString
  117. }
  118. return fmt.Sprintf("%f", f.Float64)
  119. }
  120. // SetValid changes this Float's value and also sets it to be non-null.
  121. func (f *Float) SetValid(n float64) {
  122. f.Float64 = n
  123. f.Valid = true
  124. }
  125. // Ptr returns a pointer to this Float's value, or a nil pointer if this Float is null.
  126. func (f Float) Ptr() *float64 {
  127. if !f.Valid {
  128. return nil
  129. }
  130. return &f.Float64
  131. }
  132. // IsZero returns true for invalid Floats, for future omitempty support (Go 1.4?)
  133. // A non-null Float with a 0 value will not be considered zero.
  134. func (f Float) IsZero() bool {
  135. return !f.Valid
  136. }