github.com/go-playground/pkg/v5@v5.29.1/values/option/option_common.go (about) 1 //go:build go1.18 2 // +build go1.18 3 4 package optionext 5 6 import ( 7 "encoding/json" 8 ) 9 10 // Option represents a values that represents a values existence. 11 // 12 // nil is usually used on Go however this has two problems: 13 // 1. Checking if the return values is nil is NOT enforced and can lead to panics. 14 // 2. Using nil is not good enough when nil itself is a valid value. 15 // 16 // This implements the sql.Scanner interface and can be used as a sql value for reading and writing. It supports: 17 // - String 18 // - Bool 19 // - Uint8 20 // - Float64 21 // - Int16 22 // - Int32 23 // - Int64 24 // - interface{}/any 25 // - time.Time 26 // - Struct - when type is convertable to []byte and assumes JSON. 27 // - Slice - when type is convertable to []byte and assumes JSON. 28 // - Map types - when type is convertable to []byte and assumes JSON. 29 // 30 // This also implements the `json.Marshaler` and `json.Unmarshaler` interfaces. The only caveat is a None value will result 31 // in a JSON `null` value. there is no way to hook into the std library to make `omitempty` not produce any value at 32 // this time. 33 type Option[T any] struct { 34 value T 35 isSome bool 36 } 37 38 // IsSome returns true if the option is not empty. 39 func (o Option[T]) IsSome() bool { 40 return o.isSome 41 } 42 43 // IsNone returns true if the option is empty. 44 func (o Option[T]) IsNone() bool { 45 return !o.isSome 46 } 47 48 // Unwrap returns the values if the option is not empty or panics. 49 func (o Option[T]) Unwrap() T { 50 if o.isSome { 51 return o.value 52 } 53 panic("Option.Unwrap: option is None") 54 } 55 56 // UnwrapOr returns the contained `Some` value or provided default value. 57 // 58 // Arguments passed to `UnwrapOr` are eagerly evaluated; if you are passing the result of a function call, 59 // look to use `UnwrapOrElse`, which can be lazily evaluated. 60 func (o Option[T]) UnwrapOr(value T) T { 61 if o.isSome { 62 return o.value 63 } 64 return value 65 } 66 67 // UnwrapOrElse returns the contained `Some` value or computes it from a provided function. 68 func (o Option[T]) UnwrapOrElse(fn func() T) T { 69 if o.isSome { 70 return o.value 71 } 72 return fn() 73 } 74 75 // UnwrapOrDefault returns the contained `Some` value or the default value of the type T. 76 func (o Option[T]) UnwrapOrDefault() T { 77 return o.value 78 } 79 80 // And calls the provided function with the contained value if the option is Some, returns the None value otherwise. 81 func (o Option[T]) And(fn func(T) T) Option[T] { 82 if o.isSome { 83 o.value = fn(o.value) 84 } 85 return o 86 } 87 88 // AndThen calls the provided function with the contained value if the option is Some, returns the None value otherwise. 89 // 90 // This differs from `And` in that the provided function returns an Option[T] allowing changing of the Option value 91 // itself. 92 func (o Option[T]) AndThen(fn func(T) Option[T]) Option[T] { 93 if o.isSome { 94 return fn(o.value) 95 } 96 return o 97 } 98 99 // Some creates a new Option with the given values. 100 func Some[T any](value T) Option[T] { 101 return Option[T]{value, true} 102 } 103 104 // None creates an empty Option that represents no values. 105 func None[T any]() Option[T] { 106 return Option[T]{} 107 } 108 109 // MarshalJSON implements the `json.Marshaler` interface. 110 func (o Option[T]) MarshalJSON() ([]byte, error) { 111 if o.isSome { 112 return json.Marshal(o.value) 113 } 114 return []byte("null"), nil 115 } 116 117 // UnmarshalJSON implements the `json.Unmarshaler` interface. 118 func (o *Option[T]) UnmarshalJSON(data []byte) error { 119 if len(data) == 4 && string(data[:4]) == "null" { 120 *o = None[T]() 121 return nil 122 } 123 var v T 124 err := json.Unmarshal(data, &v) 125 if err != nil { 126 return err 127 } 128 *o = Some(v) 129 return nil 130 }