| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- package null
- import (
- "database/sql"
- "encoding/json"
- "fmt"
- "math"
- "reflect"
- "strconv"
- )
- const (
- nullString = "null"
- )
- // Float is a nullable float64.
- // It does not consider zero values to be null.
- // It will decode to null, not zero, if null.
- type Float struct {
- sql.NullFloat64
- }
- // NewFloat creates a new Float
- func NewFloat(f float64, valid bool) Float {
- return Float{
- NullFloat64: sql.NullFloat64{
- Float64: f,
- Valid: valid,
- },
- }
- }
- // FloatFrom creates a new Float that will always be valid.
- func FloatFrom(f float64) Float {
- return NewFloat(f, true)
- }
- // FloatFromPtr creates a new Float that be null if f is nil.
- func FloatFromPtr(f *float64) Float {
- if f == nil {
- return NewFloat(0, false)
- }
- return NewFloat(*f, true)
- }
- // FloatFromString creates a new Float from string f.
- // If the string is equal to the value of nullString then the Float will be null.
- // An empty string f will return an error.
- func FloatFromString(f string, nullString string) (Float, error) {
- if f == nullString {
- return FloatFromPtr(nil), nil
- }
- fV, err := strconv.ParseFloat(f, 64)
- if err != nil {
- return Float{}, err
- }
- return FloatFrom(fV), nil
- }
- // UnmarshalJSON implements json.Unmarshaler.
- // It supports number and null input.
- // 0 will not be considered a null Float.
- // It also supports unmarshalling a sql.NullFloat64.
- func (f *Float) UnmarshalJSON(data []byte) error {
- var err error
- var v interface{}
- if err = json.Unmarshal(data, &v); err != nil {
- return err
- }
- switch x := v.(type) {
- case float64:
- f.Float64 = x
- case map[string]interface{}:
- err = json.Unmarshal(data, &f.NullFloat64)
- case nil:
- f.Valid = false
- return nil
- default:
- err = fmt.Errorf("json: cannot unmarshal %v into Go value of type null.Float", reflect.TypeOf(v).Name())
- }
- f.Valid = err == nil
- return err
- }
- // UnmarshalText implements encoding.TextUnmarshaler.
- // It will unmarshal to a null Float if the input is a blank or not an integer.
- // It will return an error if the input is not an integer, blank, or "null".
- func (f *Float) UnmarshalText(text []byte) error {
- str := string(text)
- if str == "" || str == nullString {
- f.Valid = false
- return nil
- }
- var err error
- f.Float64, err = strconv.ParseFloat(string(text), 64)
- f.Valid = err == nil
- return err
- }
- // MarshalJSON implements json.Marshaler.
- // It will encode null if this Float is null.
- func (f Float) MarshalJSON() ([]byte, error) {
- if !f.Valid || math.IsNaN(f.Float64) {
- return []byte(nullString), nil
- }
- return []byte(strconv.FormatFloat(f.Float64, 'f', -1, 64)), nil
- }
- // MarshalText implements encoding.TextMarshaler.
- // It will encode a blank string if this Float is null.
- func (f Float) MarshalText() ([]byte, error) {
- if !f.Valid {
- return []byte{}, nil
- }
- return []byte(strconv.FormatFloat(f.Float64, 'f', -1, 64)), nil
- }
- // MarshalText implements encoding.TextMarshaler.
- // It will encode a blank string if this Float is null.
- func (f Float) String() string {
- if !f.Valid {
- return nullString
- }
- return fmt.Sprintf("%1.3f", f.Float64)
- }
- // FullString returns float as string in full precision
- func (f Float) FullString() string {
- if !f.Valid {
- return nullString
- }
- return fmt.Sprintf("%f", f.Float64)
- }
- // SetValid changes this Float's value and also sets it to be non-null.
- func (f *Float) SetValid(n float64) {
- f.Float64 = n
- f.Valid = true
- }
- // Ptr returns a pointer to this Float's value, or a nil pointer if this Float is null.
- func (f Float) Ptr() *float64 {
- if !f.Valid {
- return nil
- }
- return &f.Float64
- }
- // IsZero returns true for invalid Floats, for future omitempty support (Go 1.4?)
- // A non-null Float with a 0 value will not be considered zero.
- func (f Float) IsZero() bool {
- return !f.Valid
- }
|