float.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  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. // UnmarshalJSON implements json.Unmarshaler.
  39. // It supports number and null input.
  40. // 0 will not be considered a null Float.
  41. // It also supports unmarshalling a sql.NullFloat64.
  42. func (f *Float) UnmarshalJSON(data []byte) error {
  43. var err error
  44. var v interface{}
  45. if err = json.Unmarshal(data, &v); err != nil {
  46. return err
  47. }
  48. switch x := v.(type) {
  49. case float64:
  50. f.Float64 = x
  51. case map[string]interface{}:
  52. err = json.Unmarshal(data, &f.NullFloat64)
  53. case nil:
  54. f.Valid = false
  55. return nil
  56. default:
  57. err = fmt.Errorf("json: cannot unmarshal %v into Go value of type null.Float", reflect.TypeOf(v).Name())
  58. }
  59. f.Valid = err == nil
  60. return err
  61. }
  62. // UnmarshalText implements encoding.TextUnmarshaler.
  63. // It will unmarshal to a null Float if the input is a blank or not an integer.
  64. // It will return an error if the input is not an integer, blank, or "null".
  65. func (f *Float) UnmarshalText(text []byte) error {
  66. str := string(text)
  67. if str == "" || str == nullString {
  68. f.Valid = false
  69. return nil
  70. }
  71. var err error
  72. f.Float64, err = strconv.ParseFloat(string(text), 64)
  73. f.Valid = err == nil
  74. return err
  75. }
  76. // MarshalJSON implements json.Marshaler.
  77. // It will encode null if this Float is null.
  78. func (f Float) MarshalJSON() ([]byte, error) {
  79. if !f.Valid {
  80. return []byte(nullString), nil
  81. }
  82. return []byte(strconv.FormatFloat(f.Float64, 'f', -1, 64)), nil
  83. }
  84. // MarshalText implements encoding.TextMarshaler.
  85. // It will encode a blank string if this Float is null.
  86. func (f Float) MarshalText() ([]byte, error) {
  87. if !f.Valid {
  88. return []byte{}, nil
  89. }
  90. return []byte(strconv.FormatFloat(f.Float64, 'f', -1, 64)), nil
  91. }
  92. // MarshalText implements encoding.TextMarshaler.
  93. // It will encode a blank string if this Float is null.
  94. func (f Float) String() string {
  95. if !f.Valid {
  96. return nullString
  97. }
  98. return fmt.Sprintf("%1.3f", f.Float64)
  99. }
  100. // FullString returns float as string in full precision
  101. func (f Float) FullString() string {
  102. if !f.Valid {
  103. return nullString
  104. }
  105. return fmt.Sprintf("%f", f.Float64)
  106. }
  107. // SetValid changes this Float's value and also sets it to be non-null.
  108. func (f *Float) SetValid(n float64) {
  109. f.Float64 = n
  110. f.Valid = true
  111. }
  112. // Ptr returns a pointer to this Float's value, or a nil pointer if this Float is null.
  113. func (f Float) Ptr() *float64 {
  114. if !f.Valid {
  115. return nil
  116. }
  117. return &f.Float64
  118. }
  119. // IsZero returns true for invalid Floats, for future omitempty support (Go 1.4?)
  120. // A non-null Float with a 0 value will not be considered zero.
  121. func (f Float) IsZero() bool {
  122. return !f.Valid
  123. }