Documentation
¶
Overview ¶
Package optional provides a generic Optional type for Go.
For a lot of use cases, I don't like mixing the concepts of referencing and optionality, as it happens with pointers, so this provides an alternative.
The Optionals implemented in this package handle marshalling and unmarshalling to/from json and xml and are handling null-values, not existing values and omitzero/omitempty.
Index ¶
- type Optional
- func (o Optional[T]) Get() (value T, ok bool)
- func (o Optional[T]) MarshalJSON() ([]byte, error)
- func (o Optional[T]) MarshalXML(e *xml.Encoder, start xml.StartElement) error
- func (o Optional[T]) String() string
- func (o *Optional[T]) UnmarshalJSON(d []byte) error
- func (o *Optional[T]) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Optional ¶
type Optional[T any] struct { // contains filtered or unexported fields }
Optional represents a value of type T that may or may not be present.
func (Optional[T]) Get ¶
Get returns the value if present, and a boolean indicating its presence.
Example ¶
package main import ( "fmt" "github.com/KrischanCS/go-toolbox/optional" ) func main() { optPresent := optional.Of("value") optEmpty := optional.Empty[string]() value, ok := optPresent.Get() fmt.Printf("value 1:%s\n", value) fmt.Printf("ok 1:%t\n", ok) fmt.Println() value, ok = optEmpty.Get() fmt.Printf("value 2:%s\n", value) fmt.Printf("ok 2:%t\n", ok) }
Output: value 1:value ok 1:true value 2: ok 2:false
func (Optional[T]) MarshalJSON ¶
MarshalJSON encodes marshals the value if present or 'null' if empty.
Example ¶
package main import ( "encoding/json" "fmt" "github.com/KrischanCS/go-toolbox/optional" ) func main() { type Test struct { Value1 optional.Optional[string] `json:"value1"` Value2 optional.Optional[string] `json:"value2"` Value3 optional.Optional[string] `json:"value3,omitempty"` // omitempty will be kept, event if optional is empty Value4 optional.Optional[string] `json:"value4,omitzero"` // omitzero will correctly omit an empty optional } t := Test{ Value1: optional.Of("value1"), Value2: optional.Empty[string](), // Not setting Value3 & Value4, zero values are empty optionals, // equivalent as setting Value2 to empty explicitly } jsonBytes, err := json.MarshalIndent(t, "", " ") if err != nil { panic(err) } fmt.Println(string(jsonBytes)) }
Output: { "value1": "value1", "value2": null, "value3": null }
func (Optional[T]) MarshalXML ¶
MarshalXML encodes the value if present, otherwise it does nothing (Currently always omitemtpy behaviour).
Example ¶
package main import ( "encoding/xml" "fmt" "github.com/KrischanCS/go-toolbox/optional" ) func main() { type Test struct { Value1 optional.Optional[string] `xml:"value1"` Value2 optional.Optional[string] `xml:"value2"` // empty existing tags are considered existing empty strings Value3 optional.Optional[string] `xml:"value3,omitempty"` // omitempty will be kept, event if optional is empty } t := Test{ Value1: optional.Of("value1"), Value2: optional.Empty[string](), // Not setting Value3 & Value4, zero values are empty optionals, equivalent as setting Value2 to empty explicitly } xmlBytes, err := xml.MarshalIndent(t, "", " ") if err != nil { panic(err) } fmt.Println(string(xmlBytes)) }
Output: <Test> <value1>value1</value1> </Test>
func (Optional[T]) String ¶
String returns a string representation in the format:
- If Present: Optional[{{type}}]: {{value}}
- If Empty: Optional[{{type}}]: <empty>
Example ¶
package main import ( "fmt" "github.com/KrischanCS/go-toolbox/optional" ) func main() { optPresent := optional.Of("value") optEmpty := optional.Empty[string]() fmt.Println(optPresent.String()) fmt.Println(optEmpty.String()) }
Output: (Optional[string]: value) (Optional[string] <empty>)
func (*Optional[T]) UnmarshalJSON ¶
UnmarshalJSON creates a present Optional if the value is not 'null', otherwise an empty.
Example ¶
package main import ( "encoding/json" "fmt" "github.com/KrischanCS/go-toolbox/optional" ) func main() { type Test struct { Value1 optional.Optional[string] `json:"value1"` Value2 optional.Optional[string] `json:"value2"` Value3 optional.Optional[string] `json:"value3"` } jsonBytes := []byte(`{"value1":"value1","value2":null}`) var t Test if err := json.Unmarshal(jsonBytes, &t); err != nil { panic(err) } fmt.Println(t.Value1.String()) fmt.Println(t.Value2.String()) fmt.Println(t.Value3.String()) }
Output: (Optional[string]: value1) (Optional[string] <empty>) (Optional[string] <empty>)
func (*Optional[T]) UnmarshalXML ¶
UnmarshalXML creates a present Optional if the value is not empty, otherwise an empty.
Example ¶
package main import ( "encoding/xml" "fmt" "github.com/KrischanCS/go-toolbox/optional" ) func main() { type Test struct { Value1 optional.Optional[string] `xml:"value1"` Value2 optional.Optional[string] `xml:"value2"` Value3 optional.Optional[string] `xml:"value3"` } xmlBytes := []byte(`<Test><value1>value1</value1><value2></value2></Test>`) var t Test err := xml.Unmarshal(xmlBytes, &t) if err != nil { panic(err) } fmt.Println(t.Value1.String()) fmt.Println(t.Value2.String()) // Empty existing tag will be considered existing empty string fmt.Println(t.Value3.String()) }
Output: (Optional[string]: value1) (Optional[string]: ) (Optional[string] <empty>)