optional

package module
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 23, 2024 License: MIT Imports: 13 Imported by: 2

README

go-optional

Go Reference Build Status Release License

Easy-to-use generic optional values for Go (golang).

Inspired by Java's Optional class, it enables the ability to differentiate a value that has its zero value due to not being set from having a zero value that was explicitly set, drastically reducing the need for pointers in a lot of use cases.

Installation

Install using go install:

go install github.com/neocotic/go-optional

Then import the package into your own code:

import "github.com/neocotic/go-optional"

Documentation

Documentation is available on pkg.go.dev. It contains an overview and reference.

Example

Basic usage:

opt := optional.Of(0)
opt.IsPresent()  // true
opt.Get()        // 0, true

opt := optional.Of(123)
opt.IsPresent()  // true
opt.Get()        // 123, true

var external []int
opt := optional.OfNillable(external)
opt.IsPresent()      // false
opt.Get()            // nil, false
opt.OrElse([]int{})  // []int{}

opt := optional.Empty[string]()
opt.IsPresent()  // false
opt.Get()        // "", false

Optionals are also intended to be used as struct fields and support JSON, XML, and YAML marshaling and unmarshaling out-of-the-box. That said; the very nature of optionals leans more towards unmarshaling.

type Example struct {
    Number Optional[int]    `json:"number"`
    Text   Optional[string] `json:"text"`
}

var example Example
err := json.Unmarshal([]byte(`{"text": "abc"}`, &example)
if err != nil {
    panic(err)
}
example.Number.Get()  // 0, false
example.Text.Get()    // "abc", true

There's a load of other functions and methods on Optional (along with its own sort sub-package) to explore, all with documented examples.

Issues

If you have any problems or would like to see changes currently in development you can do so here.

Contributors

If you want to contribute, you're a legend! Information on how you can do so can be found in CONTRIBUTING.md. We want your suggestions and pull requests!

A list of contributors can be found in AUTHORS.md.

License

Copyright © 2024 neocotic

See LICENSE.md for more information on our MIT license.

Documentation

Overview

Package optional enables the ability to differentiate a value that has its zero value due to not being set from having a zero value that was explicitly set.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Compare

func Compare[T cmp.Ordered](x, y Optional[T]) int

Compare returns the following:

  • -1 if x has not value present and y does; or if both have a value present and the value of x is less than that of y
  • 0 if neither x nor y have a value present; or if both have a value present that are equal
  • +1 if x has a value present and y does not; or if both have a value present and the value of x is greater than that of y

For floating-point types, a NaN is considered less than any non-NaN, a NaN is considered equal to a NaN, and -0.0 is equal to 0.0.

Example (Int)
fmt.Println(Compare(Empty[int](), Of(0)))
fmt.Println(Compare(Of(0), Of(123)))

fmt.Println(Compare(Empty[int](), Empty[int]()))
fmt.Println(Compare(Of(0), Of(0)))
fmt.Println(Compare(Of(123), Of(123)))

fmt.Println(Compare(Of(0), Empty[int]()))
fmt.Println(Compare(Of(123), Of(0)))
Output:

-1
-1
0
0
0
1
1
Example (String)
fmt.Println(Compare(Empty[string](), Of("")))
fmt.Println(Compare(Of(""), Of("abc")))

fmt.Println(Compare(Empty[string](), Empty[string]()))
fmt.Println(Compare(Of(""), Of("")))
fmt.Println(Compare(Of("abc"), Of("abc")))

fmt.Println(Compare(Of(""), Empty[string]()))
fmt.Println(Compare(Of("abc"), Of("")))
Output:

-1
-1
0
0
0
1
1

func GetAny

func GetAny[T any](opts ...Optional[T]) []T

GetAny returns a slice containing only the values of any given Optional that has a value present, where possible.

Example (Int)
example.PrintValues(GetAny[int]())
example.PrintValues(GetAny(Empty[int]()))
example.PrintValues(GetAny(Empty[int](), Of(0), Of(123)))
Output:

[]
[]
[0 123]
Example (String)
example.PrintValues(GetAny[string]())
example.PrintValues(GetAny(Empty[string]()))
example.PrintValues(GetAny(Empty[string](), Of("abc"), Of("")))
Output:

[]
[]
["abc" ""]

func MustFind

func MustFind[T any](opts ...Optional[T]) T

MustFind returns the value of the first given Optional that has a value present, otherwise panics.

Example (Int)
example.PrintValue(MustFind(Empty[int](), Of(0), Of(123)))
Output:

0
Example (Panic)
defer func() {
	fmt.Println(recover())
}()

MustFind(Empty[int]())
Output:

go-optional: value not present
Example (String)
example.PrintValue(MustFind(Empty[string](), Of("abc"), Of("")))
Output:

"abc"

func RequireAny

func RequireAny[T any](opts ...Optional[T]) []T

RequireAny returns a slice containing only the values of any given Optional that has a value present, panicking only if no Optional could be found with a value present.

Example (Int)
example.PrintValues(RequireAny(Empty[int](), Of(0), Of(123)))
Output:

[0 123]
Example (Panic)
defer func() {
	fmt.Println(recover())
}()

RequireAny(Empty[int]())
Output:

go-optional: value not present
Example (String)
example.PrintValues(RequireAny(Empty[string](), Of(""), Of("abc")))
Output:

["" "abc"]

Types

type Optional

type Optional[T any] struct {
	// contains filtered or unexported fields
}

Optional contains an immutable value as well as an indication whether it was explicitly set. This can be especially useful when needing to differentiate the source of a zero value.

For the best experience when marshaling a struct with Optional struct field types, the following information may be useful;

  • json: it's recommended to include the "omitempty" tag option and have the Optional field type declared as a pointer, otherwise the "omitempty" tag option is ignored
  • xml: seems to work perfectly as expected
  • yaml: it's recommended to include the "omitempty" tag option

That said; Optional is intended more for reading input rather than writing output. An important note for unmarshalling is that yaml, unlike json, will skip an Optional struct field that has been given an explicit null value, resulting in an empty Optional.

Similarly, Optional works as expected with the sql package, where an Optional without a value present is considered equal to NULL. By implementing sql.Scanner and driver.Valuer, an Optional can be used seamlessly with scanning in sql.Rows and as a query parameter in sql.DB.

func Empty

func Empty[T any]() Optional[T]

Empty returns an Optional with no value. It's the equivalent of using a zero value Optional.

Example (Int)
example.Print(Empty[int]())
Output:

<empty>
Example (String)
example.Print(Empty[string]())
Output:

<empty>

func Find

func Find[T any](opts ...Optional[T]) Optional[T]

Find returns the first given Optional that has a value present, otherwise an empty Optional.

Example (Int)
example.Print(Find[int]())
example.Print(Find(Empty[int]()))
example.Print(Find(Empty[int](), Of(0), Of(123)))
example.Print(Find(Empty[int](), Of(123), Of(0)))
Output:

<empty>
<empty>
0
123
Example (String)
example.Print(Find[string]())
example.Print(Find(Empty[string]()))
example.Print(Find(Empty[string](), Of(""), Of("abc")))
example.Print(Find(Empty[string](), Of("abc"), Of("")))
Output:

<empty>
<empty>
""
"abc"

func FlatMap

func FlatMap[T, M any](opt Optional[T], fn func(value T) Optional[M]) Optional[M]

FlatMap calls the given function and returns the Optional returned by it if the Optional provided has a value present, otherwise an empty Optional is returned.

Warning: While fn will only be called if opt has a value present, that value may still be nil or the zero value for T.

Example (Int)
mapper := func(value int) Optional[string] {
	if value == 0 {
		return Empty[string]()
	}
	return Of(strconv.FormatInt(int64(value), 10))
}

example.Print(FlatMap(Empty[int](), mapper))
example.Print(FlatMap(Of(0), mapper))
example.Print(FlatMap(Of(123), mapper))
Output:

<empty>
<empty>
"123"
Example (String)
mapper := func(value string) Optional[int] {
	if value == "" {
		return Empty[int]()
	}
	i, err := strconv.ParseInt(value, 10, 0)
	if err != nil {
		log.Fatal(err)
	}
	return OfZeroable(int(i))
}

example.Print(FlatMap(Empty[string](), mapper))
example.Print(FlatMap(Of(""), mapper))
example.Print(FlatMap(Of("0"), mapper))
example.Print(FlatMap(Of("123"), mapper))
Output:

<empty>
<empty>
<empty>
123

func Map

func Map[T, M any](opt Optional[T], fn func(value T) M) Optional[M]

Map returns an Optional whose value is mapped from the Optional provided using the given function, if present, otherwise an empty Optional.

Warning: While fn will only be called if opt has a value present, that value may still be nil or the zero value for T.

Example (Int)
mapper := func(value int) string {
	return strconv.FormatInt(int64(value), 10)
}

example.Print(Map(Empty[int](), mapper))
example.Print(Map(Of(0), mapper))
example.Print(Map(Of(123), mapper))
Output:

<empty>
"0"
"123"
Example (String)
mapper := func(value string) int {
	i, err := strconv.ParseInt(value, 10, 0)
	if err != nil {
		log.Fatal(err)
	}
	return int(i)
}

example.Print(Map(Empty[string](), mapper))
example.Print(Map(Of("0"), mapper))
example.Print(Map(Of("123"), mapper))
Output:

<empty>
0
123

func Of

func Of[T any](value T) Optional[T]

Of returns an Optional with the given value present.

Example (Int)
example.Print(Of(0))
example.Print(Of(123))
Output:

0
123
Example (Int_pointer)
example.Print(Of((*int)(nil)))
example.Print(Of(ptrs.ZeroInt()))
example.Print(Of(ptrs.Int(123)))
Output:

<nil>
&0
&123
Example (String)
example.Print(Of(""))
example.Print(Of("abc"))
Output:

""
"abc"
Example (String_pointer)
example.Print(Of((*string)(nil)))
example.Print(Of(ptrs.ZeroString()))
example.Print(Of(ptrs.String("abc")))
Output:

<nil>
&""
&"abc"

func OfNillable

func OfNillable[T any](value T) Optional[T]

OfNillable returns an Optional with the given value present only if value is nil. That is; unlike Of, OfNillable treats a nil value as absent and so the returned Optional will be empty.

Since T can be any type, whether value is nil is checked reflectively.

Example (Int)
example.Print(OfNillable(0))
example.Print(OfNillable(123))
Output:

0
123
Example (Int_pointer)
example.Print(OfNillable((*int)(nil)))
example.Print(OfNillable(ptrs.ZeroInt()))
example.Print(OfNillable(ptrs.Int(123)))
Output:

<empty>
&0
&123
Example (String)
example.Print(OfNillable(""))
example.Print(OfNillable("abc"))
Output:

""
"abc"
Example (String_pointer)
example.Print(OfNillable((*string)(nil)))
example.Print(OfNillable(ptrs.ZeroString()))
example.Print(OfNillable(ptrs.String("abc")))
Output:

<empty>
&""
&"abc"

func OfPointer

func OfPointer[T any](value T) Optional[*T]

OfPointer returns an Optional with the given value present as a pointer.

Example (Int)
example.Print(OfPointer(0))
example.Print(OfPointer(123))
Output:

&0
&123
Example (String)
example.Print(OfPointer(""))
example.Print(OfPointer("abc"))
Output:

&""
&"abc"

func OfZeroable

func OfZeroable[T any](value T) Optional[T]

OfZeroable returns an Optional with the given value present only if value does not equal the zero value for T. That is; unlike Of, OfZeroable treats a value of zero as absent and so the returned Optional will be empty.

Since T can be any type, whether value is equal to the zero value of T is checked reflectively.

Example (Int)
example.Print(OfZeroable(0))
example.Print(OfZeroable(123))
Output:

<empty>
123
Example (Int_pointer)
example.Print(OfZeroable((*int)(nil)))
example.Print(OfZeroable(ptrs.ZeroInt()))
example.Print(OfZeroable(ptrs.Int(123)))
Output:

<empty>
&0
&123
Example (String)
example.Print(OfZeroable(""))
example.Print(OfZeroable("abc"))
Output:

<empty>
"abc"
Example (String_pointer)
example.Print(OfZeroable((*string)(nil)))
example.Print(OfZeroable(ptrs.ZeroString()))
example.Print(OfZeroable(ptrs.String("abc")))
Output:

<empty>
&""
&"abc"

func TryFlatMap

func TryFlatMap[T, M any](opt Optional[T], fn func(value T) (Optional[M], error)) (Optional[M], error)

TryFlatMap calls the given function and returns the Optional returned by it if the Optional provided has a value present, otherwise an empty Optional is returned. The difference from FlatMap is that the given function may return an error which, if not nil, will be returned by TryFlatMap.

Warning: While fn will only be called if opt has a value present, that value may still be nil or the zero value for T.

Example (Int)
mapper := func(value int) (Optional[string], error) {
	if value == 0 {
		return Empty[string](), nil
	}
	return Of(strconv.FormatInt(int64(value), 10)), nil
}

example.PrintTry(TryFlatMap(Empty[int](), mapper))
example.PrintTry(TryFlatMap(Of(0), mapper))
example.PrintTry(TryFlatMap(Of(123), mapper))
Output:

<empty> <nil>
<empty> <nil>
"123" <nil>
Example (String)
mapper := func(value string) (Optional[int], error) {
	if value == "" {
		return Empty[int](), nil
	}
	i, err := strconv.ParseInt(value, 10, 0)
	if err != nil {
		return Empty[int](), err
	}
	return OfZeroable(int(i)), nil
}

example.PrintTry(TryFlatMap(Empty[string](), mapper))
example.PrintTry(TryFlatMap(Of(""), mapper))
example.PrintTry(TryFlatMap(Of("0"), mapper))
example.PrintTry(TryFlatMap(Of("123"), mapper))
example.PrintTry(TryFlatMap(Of("abc"), mapper))
Output:

<empty> <nil>
<empty> <nil>
<empty> <nil>
123 <nil>
<empty> "strconv.ParseInt: parsing \"abc\": invalid syntax"

func TryMap

func TryMap[T, M any](opt Optional[T], fn func(value T) (M, error)) (Optional[M], error)

TryMap returns an Optional whose value is mapped from the Optional provided using the given function, if present, otherwise an empty Optional. The difference from Map is that the given function may return an error which, if not nil, will be returned by TryMap.

Warning: While fn will only be called if opt has a value present, that value may still be nil or the zero value for T.

Example (Int)
mapper := func(value int) (string, error) {
	return strconv.FormatInt(int64(value), 10), nil
}

example.PrintTry(TryMap(Empty[int](), mapper))
example.PrintTry(TryMap(Of(0), mapper))
example.PrintTry(TryMap(Of(123), mapper))
Output:

<empty> <nil>
"0" <nil>
"123" <nil>
Example (String)
mapper := func(value string) (int, error) {
	i, err := strconv.ParseInt(value, 10, 0)
	return int(i), err
}

example.PrintTry(TryMap(Empty[string](), mapper))
example.PrintTry(TryMap(Of("0"), mapper))
example.PrintTry(TryMap(Of("123"), mapper))
example.PrintTry(TryMap(Of("abc"), mapper))
Output:

<empty> <nil>
0 <nil>
123 <nil>
<empty> "strconv.ParseInt: parsing \"abc\": invalid syntax"

func (Optional[T]) Filter

func (o Optional[T]) Filter(fn func(value T) bool) Optional[T]

Filter returns the Optional if it has a value present that the given function returns true for, otherwise an empty Optional.

Warning: While fn will only be called if Optional has a value present, that value may still be nil or the zero value for T.

Example (Int)
isPos := func(value int) bool {
	return value >= 0
}

example.Print(Empty[int]().Filter(isPos))
example.Print(Of(-123).Filter(isPos))
example.Print(Of(0).Filter(isPos))
example.Print(Of(123).Filter(isPos))
Output:

<empty>
<empty>
0
123
Example (String)
isLower := func(value string) bool {
	return !strings.ContainsFunc(value, unicode.IsUpper)
}

example.Print(Empty[string]().Filter(isLower))
example.Print(Of("ABC").Filter(isLower))
example.Print(Of("").Filter(isLower))
example.Print(Of("abc").Filter(isLower))
Output:

<empty>
<empty>
""
"abc"

func (Optional[T]) Get

func (o Optional[T]) Get() (T, bool)

Get returns the value of the Optional and whether it is present.

Example (Int)
example.PrintGet(Empty[int]().Get())
example.PrintGet(Of(0).Get())
example.PrintGet(Of(123).Get())
Output:

0 false
0 true
123 true
Example (String)
example.PrintGet(Empty[string]().Get())
example.PrintGet(Of("").Get())
example.PrintGet(Of("abc").Get())
Output:

"" false
"" true
"abc" true

func (Optional[T]) IfPresent

func (o Optional[T]) IfPresent(fn func(value T))

IfPresent calls the given function only the Optional has a value present, passing the value to the function.

Warning: While fn will only be called if Optional has a value present, that value may still be nil or the zero value for T.

Example (Int)
Empty[int]().IfPresent(example.PrintValue[int]) // Does nothing
Of(0).IfPresent(example.PrintValue[int])
Of(123).IfPresent(example.PrintValue[int])
Output:

0
123
Example (String)
Empty[string]().IfPresent(example.PrintValue[string]) // Does nothing
Of("").IfPresent(example.PrintValue[string])
Of("abc").IfPresent(example.PrintValue[string])
Output:

""
"abc"

func (Optional[T]) IsEmpty

func (o Optional[T]) IsEmpty() bool

IsEmpty returns whether the value of the Optional is absent. That is; it has NOT been explicitly set.

IsEmpty is effectively the inverse of IsPresent. It's important to note that IsEmpty will not return true if the underlying value of the Optional is equal to the zero value for T and in no way checks the length of the underlying value but instead only if the value is absent.

Example (Int)
fmt.Println(Empty[int]().IsEmpty())
fmt.Println(Of(0).IsEmpty())
fmt.Println(Of(123).IsEmpty())
Output:

true
false
false
Example (String)
fmt.Println(Empty[string]().IsEmpty())
fmt.Println(Of("").IsEmpty())
fmt.Println(Of("abc").IsEmpty())
Output:

true
false
false

func (Optional[T]) IsPresent

func (o Optional[T]) IsPresent() bool

IsPresent returns whether the value of the Optional is present. That is; it has been explicitly set.

Example (Int)
fmt.Println(Empty[int]().IsPresent())
fmt.Println(Of(0).IsPresent())
fmt.Println(Of(123).IsPresent())
Output:

false
true
true
Example (String)
fmt.Println(Empty[string]().IsPresent())
fmt.Println(Of("").IsPresent())
fmt.Println(Of("abc").IsPresent())
Output:

false
true
true

func (Optional[T]) IsZero

func (o Optional[T]) IsZero() bool

IsZero returns whether the value of the Optional is absent. That is; it has NOT been explicitly set.

IsZero is effectively the inverse of IsPresent and an alternative for IsEmpty that conforms to the yaml.IsZeroer interface. It's important to note that IsZero will not return true if the underlying value of the Optional is equal to the zero value for T but instead only if the value is absent.

Example (Int)
fmt.Println(Empty[int]().IsZero())
fmt.Println(Of(0).IsZero())
fmt.Println(Of(123).IsZero())
Output:

true
false
false
Example (String)
fmt.Println(Empty[string]().IsZero())
fmt.Println(Of("").IsZero())
fmt.Println(Of("abc").IsZero())
Output:

true
false
false

func (Optional[T]) MarshalJSON

func (o Optional[T]) MarshalJSON() ([]byte, error)

MarshalJSON marshals the value of the Optional into JSON, if present, otherwise returns a null-like value.

An error is returned if unable to marshal the value.

Example
// json omitempty option does not apply to zero value structs
type MyStruct struct {
	Number Optional[int]    `json:"number,omitempty"`
	Text   Optional[string] `json:"text,omitempty"`
}

example.PrintMarshalled(json.Marshal(Of(MyStruct{})))
example.PrintMarshalled(json.Marshal(Of(MyStruct{Number: Of(0), Text: Of("")})))
example.PrintMarshalled(json.Marshal(Of(MyStruct{Number: Of(123), Text: Of("abc")})))
Output:

{"number":null,"text":null} <nil>
{"number":0,"text":""} <nil>
{"number":123,"text":"abc"} <nil>
Example (Pointers)
type MyStruct struct {
	Number *Optional[int]    `json:"number,omitempty"`
	Text   *Optional[string] `json:"text,omitempty"`
}

example.PrintMarshalled(json.Marshal(Of(MyStruct{})))
example.PrintMarshalled(json.Marshal(Of(MyStruct{Number: ptrs.Value(Of(0)), Text: ptrs.Value(Of(""))})))
example.PrintMarshalled(json.Marshal(Of(MyStruct{Number: ptrs.Value(Of(123)), Text: ptrs.Value(Of("abc"))})))
Output:

{} <nil>
{"number":0,"text":""} <nil>
{"number":123,"text":"abc"} <nil>

func (Optional[T]) MarshalXML

func (o Optional[T]) MarshalXML(e *xml.Encoder, start xml.StartElement) error

MarshalXML marshals the encoded value of the Optional into XML, if present, otherwise nothing is written to the given encoder.

An error is returned if unable to write the value to the given encoder.

Example
type MyStruct struct {
	Number Optional[int]    `xml:"number,omitempty"`
	Text   Optional[string] `xml:"text,omitempty"`
}

example.PrintMarshalled(xml.Marshal(Of(MyStruct{})))
example.PrintMarshalled(xml.Marshal(Of(MyStruct{Number: Of(0), Text: Of("")})))
example.PrintMarshalled(xml.Marshal(Of(MyStruct{Number: Of(123), Text: Of("abc")})))
Output:

<MyStruct></MyStruct> <nil>
<MyStruct><number>0</number><text></text></MyStruct> <nil>
<MyStruct><number>123</number><text>abc</text></MyStruct> <nil>

func (Optional[T]) MarshalYAML

func (o Optional[T]) MarshalYAML() (any, error)

MarshalYAML marshals the value of the Optional into YAML, if present, otherwise returns a null-like value.

An error is returned if unable to marshal the value.

Example
type MyStruct struct {
	Number Optional[int]    `yaml:"number,omitempty"`
	Text   Optional[string] `yaml:"text,omitempty"`
}

example.PrintMarshalled(yaml.Marshal(Of(MyStruct{})))
example.PrintMarshalled(yaml.Marshal(Of(MyStruct{Number: Of(0), Text: Of("")})))
example.PrintMarshalled(yaml.Marshal(Of(MyStruct{Number: Of(123), Text: Of("abc")})))
Output:

{} <nil>
number: 0
text: "" <nil>
number: 123
text: abc <nil>

func (Optional[T]) OrElse

func (o Optional[T]) OrElse(other T) T

OrElse returns the value of the Optional if present, otherwise other.

Example (Int)
defaultVal := -1

example.PrintValue(Empty[int]().OrElse(defaultVal))
example.PrintValue(Of(0).OrElse(defaultVal))
example.PrintValue(Of(123).OrElse(defaultVal))
Output:

-1
0
123
Example (String)
defaultVal := "unknown"

example.PrintValue(Empty[string]().OrElse(defaultVal))
example.PrintValue(Of("").OrElse(defaultVal))
example.PrintValue(Of("abc").OrElse(defaultVal))
Output:

"unknown"
""
"abc"

func (Optional[T]) OrElseGet

func (o Optional[T]) OrElseGet(other func() T) T

OrElseGet returns the value of the Optional if present, otherwise calls other and returns its return value. This is recommended over OrElse in cases where a default value is expensive to initialize so lazy-initializes it.

Example (Int)
defaultFunc := func() int {
	return -1
}

example.PrintValue(Empty[int]().OrElseGet(defaultFunc))
example.PrintValue(Of(0).OrElseGet(defaultFunc))
example.PrintValue(Of(123).OrElseGet(defaultFunc))
Output:

-1
0
123
Example (String)
defaultFunc := func() string {
	return "unknown"
}

example.PrintValue(Empty[string]().OrElseGet(defaultFunc))
example.PrintValue(Of("").OrElseGet(defaultFunc))
example.PrintValue(Of("abc").OrElseGet(defaultFunc))
Output:

"unknown"
""
"abc"

func (Optional[T]) OrElseTryGet

func (o Optional[T]) OrElseTryGet(other func() (T, error)) (T, error)

OrElseTryGet returns the value of the Optional if present, otherwise calls other and returns its return value. This is recommended over OrElse in cases where a default value is expensive to initialize so lazy-initializes it. The difference from OrElseGet is that the given function may return an error which, if not nil, will be returned by OrElseTryGet.

Example (Int)
defaultFunc := func() (int, error) {
	return -1, nil
}

example.PrintTryValue(Empty[int]().OrElseTryGet(defaultFunc))
example.PrintTryValue(Of(0).OrElseTryGet(defaultFunc))
example.PrintTryValue(Of(123).OrElseTryGet(defaultFunc))
Output:

-1 <nil>
0 <nil>
123 <nil>
Example (String)
var defaultStringUsed bool
defaultFunc := func() (string, error) {
	if defaultStringUsed {
		return "", errors.New("default string already used")
	}
	defaultStringUsed = true
	return "unknown", nil
}

example.PrintTryValue(Empty[string]().OrElseTryGet(defaultFunc))
example.PrintTryValue(Of("").OrElseTryGet(defaultFunc))
example.PrintTryValue(Of("abc").OrElseTryGet(defaultFunc))
example.PrintTryValue(Empty[string]().OrElseTryGet(defaultFunc))
Output:

"unknown" <nil>
"" <nil>
"abc" <nil>
"" "default string already used"

func (Optional[T]) Require

func (o Optional[T]) Require() T

Require returns the value of the Optional only if present, otherwise panics.

Example (Int)
example.PrintValue(Of(0).Require())
example.PrintValue(Of(123).Require())
Output:

0
123
Example (Panic)
defer func() {
	fmt.Println(recover())
}()

Empty[int]().Require()
Output:

go-optional: value not present
Example (String)
example.PrintValue(Of("").Require())
example.PrintValue(Of("abc").Require())
Output:

""
"abc"

func (*Optional[T]) Scan added in v0.1.1

func (o *Optional[T]) Scan(src any) error

Scan assigns the given value from a database driver into the value of the Optional, where possible. See sql.Scanner for more information.

Scan supports scanning all the same types as sql.Rows except for sql.Rows itself. If src is nil, the Optional will be empty, otherwise it will have an assigned (and often converted) value present. If the value of the Optional is a sql.Scanner itself, its own Scan method will be called to assign src.

An error is returned if src cannot be stored within the Optional without loss of information or there is a type mismatch.

Example
rows, err := db.QueryContext(ctx, "SELECT name, age FROM users")
if err != nil {
	log.Fatal(err)
}
defer rows.Close()

users := make(map[string]Optional[int])
for rows.Next() {
	var (
		age  Optional[int]
		name string
	)
	if err = rows.Scan(&name, &age); err != nil {
		log.Fatal(err)
	}
	users[name] = age
}
if err = rows.Err(); err != nil {
	log.Fatal(err)
}

log.Printf("user demographics: %s", users)
Output:

func (Optional[T]) String

func (o Optional[T]) String() string

String returns a string representation of the underlying value, if any.

Example (Int)
fmt.Printf("%q\n", Empty[int]().String())
fmt.Printf("%q\n", Of(0).String())
fmt.Printf("%q\n", Of(123).String())
Output:

"<empty>"
"0"
"123"
Example (String)
fmt.Printf("%q\n", Empty[string]().String())
fmt.Printf("%q\n", Of("").String())
fmt.Printf("%q\n", Of("abc").String())
Output:

"<empty>"
""
"abc"

func (*Optional[T]) UnmarshalJSON

func (o *Optional[T]) UnmarshalJSON(data []byte) error

UnmarshalJSON unmarshalls the JSON data provided as the value for the Optional. Anytime UnmarshalJSON is called, it treats the Optional as having a value even though that value may still be nil or the zero value for T.

An error is returned if unable to unmarshal data.

Example
type MyStruct struct {
	Number Optional[int]    `json:"number"`
	Text   Optional[string] `json:"text"`
}

inputs := []string{
	`{}`,
	`{"number":null,"text":null}`,
	`{"number":0,"text":""}`,
	`{"number":123,"text":"abc"}`,
}

for _, input := range inputs {
	var output MyStruct
	if err := json.Unmarshal([]byte(input), &output); err != nil {
		log.Fatal(err)
	}

	example.Print(output.Number)
	example.Print(output.Text)
}
Output:

<empty>
<empty>
0
""
0
""
123
"abc"

func (*Optional[T]) UnmarshalXML

func (o *Optional[T]) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

UnmarshalXML unmarshalls the decoded XML element provided as the value for the Optional. Anytime UnmarshalXML is called, it treats the Optional as having a value even though that value may still be nil or the zero value for T.

An error is returned if unable to unmarshal the given element.

Example
type MyStruct struct {
	Number Optional[int]    `xml:"number"`
	Text   Optional[string] `xml:"text"`
}

inputs := []string{
	`<MyStruct></MyStruct>`,
	`<MyStruct><number>0</number><text></text></MyStruct>`,
	`<MyStruct><number>123</number><text>abc</text></MyStruct>`,
}

for _, input := range inputs {
	var output MyStruct
	if err := xml.Unmarshal([]byte(input), &output); err != nil {
		log.Fatal(err)
	}

	example.Print(output.Number)
	example.Print(output.Text)
}
Output:

<empty>
<empty>
0
""
123
"abc"

func (*Optional[T]) UnmarshalYAML

func (o *Optional[T]) UnmarshalYAML(value *yaml.Node) error

UnmarshalYAML unmarshalls the decoded YAML node provided as the value for the Optional. Anytime UnmarshalYAML is called, it treats the Optional as having a value even though that value may still be nil or the zero value for T. However, unlike UnmarshalJSON and UnmarshalXML, the YAML unmarshaler will not call UnmarshalYAML for an empty or null-like value.

An error is returned if unable to unmarshal the given node.

Example
type MyStruct struct {
	Number Optional[int]    `json:"number"`
	Text   Optional[string] `json:"text"`
}

inputs := []string{
	`{}`,
	`number: null
text: null`,
	`number: 0
text: ""`,
	`number: 123
text: abc`,
}

for _, input := range inputs {
	var output MyStruct
	if err := yaml.Unmarshal([]byte(input), &output); err != nil {
		log.Fatal(err)
	}

	example.Print(output.Number)
	example.Print(output.Text)
}
Output:

<empty>
<empty>
<empty>
<empty>
0
""
123
"abc"

func (Optional[T]) Value added in v0.1.1

func (o Optional[T]) Value() (driver.Value, error)

Value returns a driver.Value for the value of the Optional, if present, otherwise returns nil.

Effectively, nil is always returned if a value is not present, otherwise driver.DefaultParameterConverter is used to convert the value.

An error is returned if unable to return a valid driver.Value.

Example
username := "alex"
age := Of(30)
result, err := db.ExecContext(ctx, "UPDATE users SET age = ? WHERE username = ?", age, username)
if err != nil {
	log.Fatal(err)
}
rows, err := result.RowsAffected()
if err != nil {
	log.Fatal(err)
}
if rows != 1 {
	log.Fatalf("expected to affect 1 row, affected %d", rows)
}
Output:

Directories

Path Synopsis
internal
example
Package example provides helpers for generating concise examples for the module.
Package example provides helpers for generating concise examples for the module.
test
Package test provides helpers for testing the module.
Package test provides helpers for testing the module.
Package sort provides basic support for sorting slices of optional.Optional.
Package sort provides basic support for sorting slices of optional.Optional.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL