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>)