float.go 3.2 KB

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