results

package module
v1.9.0 Latest Latest
Warning

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

Go to latest
Published: Mar 9, 2025 License: Apache-2.0 Imports: 2 Imported by: 5

README

results

Package results provides generic types and functions for handling function results.

Go Reference Go Report Card

This package is designed to be simple, efficient, and easy to use while adhering to Go's idiomatic practices.

The package aims to reduce boilerplate code associated with error checking and fallback value assignment. It is particularly useful for functions that return multiple values and an error.

May

Maybe1, Maybe2, and Maybe3 types encapsulate one, two, or three values respectively, along with an error. These types simplify error handling and provide a convenient way to work with functions that may fail.

May1, May2 and May3 functions return a value of these types.

The number "1", "2" and "3" in the function name refer to the number of values excluding an error they return.

Example
value := results.May1(someFunction()).Or(defaultValue)
v1, v2 := results.May2(anotherFunction()).Or(default1, default2)

Must

Must1, Must2 and Must3 functions panic if an error occurs, which is useful for operations that should never fail during normal execution.

The number "1", "2" and "3" in the function name refer to the number of values they return.

Example
value := results.Must1(someFunction())
v1, v2 := results.Must2(anotherFunction())

Multiple Results

Functions allow you to select specific parameters from a set of two or three parameters of different types.

func Get1of2[A, B any](a A, _ B) A
    Get1of2 returns the first parameter of type A from two parameters.

func Get2of2[A, B any](_ A, b B) B
    Get2of2 returns the second parameter of type B from two parameters.

func Get1of3[A, B, C any](a A, _ B, _ C) A
    Get1of3 returns the first parameter of type A from three parameters.

func Get2of3[A, B, C any](_ A, b B, _ C) B
    Get2of3 returns the second parameter of type B from three parameters.

func Get3of3[A, B, C any](_ A, _ B, c C) C
    Get3of3 returns the third parameter of type C from three parameters.

func Get12of3[A, B, C any](a A, b B, _ C) (A, B)
    Get12of3 returns the first two parameters of types A and B from three
    parameters.

func Get23of3[A, B, C any](_ A, b B, c C) (B, C)
    Get23of3 returns the last two parameters of types B and C from three
    parameters.

You can call the functions with appropriate type parameters:

first := results.Get1of2(1, "two")
second := results.Get2of2(1, "two")
firstOfThree := results.Get1of3(1, "two", 3.0)
// ... and so on

These deprecate Take2, Drop2, Take3 and Drop3.

Example
first := results.Take2(someFunction())
second := results.Drop2(someFunction())

firstOf3 := results.Take3(anotherFunction())
the2, the3 := results.Drop3(anotherFunction())

If1 and If2

If1 and If2 functions simulate conditional expression.

Example
// someFunction returns a value of any type and a boolean value.
value := results.If1(someFunction()).Or(valueForFalse)
// anotherFunction returns two values of any type and a boolean value.
v1, v2 := results.If2(anotherFunction()).Or(fallback0, fallback1)

ErrorAs

ErrorAs returns the result of calling errors.As(err, &target).

The coding pattern using errors.As is following:

var pathError *fs.PathError
if errors.As(err, &pathError) {

Using ErrorAs is a bit more concise:

if pathError, ok := results.ErrorAs[*fs.PathError](err); ok {

Improvements:

  • Just one line.
  • Create a scope for the pathError variable.

TypeAs

TypeAs returns the result of type assertions. This is a function, so it is addressable.

Documentation

Overview

Package results provides generic types and functions for handling function results.

This package is designed to be simple, efficient, and easy to use while adhering to Go's idiomatic practices.

The package aims to reduce boilerplate code associated with error checking and fallback value assignment. It is particularly useful for functions that return multiple values and an error.

May

Maybe1, Maybe2, and Maybe3 types encapsulate one, two, or three values respectively, along with an error. These types simplify error handling and provide a convenient way to work with functions that may fail.

May1, May2 and May3 functions return a value of these types.

The number "1", "2" and "3" in the function name refer to the number of values excluding an error they return.

Example

value := results.May1(someFunction()).Or(defaultValue)
v1, v2 := results.May2(anotherFunction()).Or(default1, default2)

Must

Must1, Must2 and Must3 functions panic if an error occurs, which is useful for operations that should never fail during normal execution.

The number "1", "2" and "3" in the function name refer to the number of values they return.

Example

value := results.Must1(someFunction())
v1, v2 := results.Must2(anotherFunction())

Multiple Results

Functions allow you to select specific parameters from a set of two or three parameters of different types.

  • Get1of2 returns the first parameter from two parameters
  • Get2of2 returns the second parameter from two parameters
  • Get1of3 returns the first parameter from three parameters
  • Get2of3 returns the second parameter from three parameters
  • Get3of3 returns the third parameter from three parameters
  • Get12of3 returns the first two parameters from three parameters
  • Get23of3 returns the last two parameters from three parameters

These deprecate Take2, Drop2, Take3 and Drop3.

Example

first := results.jet1of2(1, "two")
second := results.Get2of2(1, "two")
firstOfThree := results.Get1of3(1, "two", 3.0)

If, IfFunc, If1 and If2

If, IfFunc, If1 and If2 functions simulate conditional expression.

Example

// someFunction returns a value of any type and a boolean value.
value := results.If1(someFunction()).Or(valueForFalse)
// anotherFunction returns two values of any type and a boolean value.
v1, v2 := results.If2(anotherFunction()).Or(fallback0, fallback1)

ErrorAs

The coding pattern using errors.As is following:

var pathError *fs.PathError
if errors.As(err, &pathError) {

Using ErrorAs is a bit more concise:

if pathError, ok := results.ErrorAs[*fs.PathError](err); ok {

Improvements:

  • Just one line.
  • Create a scope for the pathError variable.

TypeAs

TypeAs returns the result of type assertions. This is a funciton, so it is addressable.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Drop2 deprecated added in v1.4.0

func Drop2[T0, T1 any](_ T0, b T1) T1

Drop2 discards the first of the two provided arguments and returns the second.

Deprecated: use Get2of2 instead.

Example
package main

import (
	"fmt"
	"net"

	"github.com/goaux/results"
)

func main() {
	fmt.Println(results.Drop2(
		results.May2(net.SplitHostPort("example.com:80")).Or("localhost", "80"),
	))
}
Output:

80

func Drop3 deprecated added in v1.4.0

func Drop3[T0, T1, T2 any](_ T0, b T1, c T2) (T1, T2)

Drop3 discards the first of the three provided arguments and returns the remaining two.

Deprecated: use Get23of3 instead.

Example
package main

import (
	"fmt"

	"github.com/goaux/results"
)

func main() {
	example := func() (x, y, z int) { return 11, 22, 33 }
	fmt.Println(results.Drop3(example()))
}
Output:

22 33

func ErrorAs added in v1.6.0

func ErrorAs[T any](err error) (target T, ok bool)

ErrorAs returns the result of calling errors.As(err, &target).

The coding pattern using errors.As is following:

var pathError *fs.PathError
if errors.As(err, &pathError) {

Using ErrorAs is a bit more concise:

if pathError, ok := results.ErrorAs[*fs.PathError](err); ok {

Improvements:

  • Just one line.
  • Create a scope for the pathError variable.
Example
package main

import (
	"fmt"
	"io/fs"

	"github.com/goaux/results"
)

func main() {
	err := fmt.Errorf("wrap %w", &fs.PathError{Op: "example"})
	if pathError, ok := results.ErrorAs[*fs.PathError](err); ok {
		fmt.Println(pathError.Op)
	}
}
Output:

example

func Get12of3 added in v1.7.0

func Get12of3[A, B, C any](a A, b B, _ C) (A, B)

Get12of3 returns the first two parameters of types A and B from three parameters.

func Get1of2 added in v1.7.0

func Get1of2[A, B any](a A, _ B) A

Get1of2 returns the first parameter of type A from two parameters.

Example
package main

import (
	"fmt"
	"net"

	"github.com/goaux/results"
)

func main() {
	fmt.Println(results.Get1of2(
		results.May2(net.SplitHostPort("example.com:80")).Or("localhost", "80"),
	))
}
Output:

example.com

func Get1of3 added in v1.7.0

func Get1of3[A, B, C any](a A, _ B, _ C) A

Get1of3 returns the first parameter of type A from three parameters.

Example
package main

import (
	"fmt"

	"github.com/goaux/results"
)

func main() {
	example := func() (x, y, z int) { return 11, 22, 33 }
	fmt.Println(results.Get1of3(example()))
}
Output:

11

func Get23of3 added in v1.7.0

func Get23of3[A, B, C any](_ A, b B, c C) (B, C)

Get23of3 returns the last two parameters of types B and C from three parameters.

Example
package main

import (
	"fmt"

	"github.com/goaux/results"
)

func main() {
	example := func() (x, y, z int) { return 11, 22, 33 }
	fmt.Println(results.Get23of3(example()))
}
Output:

22 33

func Get2of2 added in v1.7.0

func Get2of2[A, B any](_ A, b B) B

Get2of2 returns the second parameter of type B from two parameters.

Example
package main

import (
	"fmt"
	"net"

	"github.com/goaux/results"
)

func main() {
	fmt.Println(results.Get2of2(
		results.May2(net.SplitHostPort("example.com:80")).Or("localhost", "80"),
	))
}
Output:

80

func Get2of3 added in v1.7.0

func Get2of3[A, B, C any](_ A, b B, _ C) B

Get2of3 returns the second parameter of type B from three parameters.

func Get3of3 added in v1.7.0

func Get3of3[A, B, C any](_ A, _ B, c C) C

Get3of3 returns the third parameter of type C from three parameters.

func If added in v1.8.0

func If[T any](ok bool, true, false T) T

If returns the true value if ok is true, otherwise the false value.

Example
package main

import (
	"fmt"

	"github.com/goaux/results"
)

func main() {
	fmt.Println(results.If(true, 42, 0))
}
Output:

42

func IfFunc added in v1.8.0

func IfFunc[T any](ok bool, true, false func() T) T

IfFunc returns the result of calling true function if ok is true, otherwise the result of calling false function.

Example
package main

import (
	"fmt"

	"github.com/goaux/results"
)

func main() {
	fmt.Println(
		results.IfFunc(
			true,
			func() string { return "42" },
			func() string { return "" },
		),
	)
}
Output:

42

func Must added in v1.3.0

func Must(err error)

Must panics if the error is non-nil. It's useful for operations that should never fail during normal execution.

func Must1 added in v1.1.0

func Must1[T any](v T, err error) T

Must1 panics if the error is non-nil, otherwise returns the value. It's useful for operations that should never fail during normal execution.

func Must2 added in v1.1.0

func Must2[T0, T1 any](v0 T0, v1 T1, err error) (T0, T1)

Must2 panics if the error is non-nil, otherwise returns the two values. It's useful for operations that should never fail during normal execution.

func Must3 added in v1.1.0

func Must3[T0, T1, T2 any](v0 T0, v1 T1, v2 T2, err error) (T0, T1, T2)

Must3 panics if the error is non-nil, otherwise returns the three values. It's useful for operations that should never fail during normal execution.

func Take2 deprecated added in v1.4.0

func Take2[T0, T1 any](a T0, _ T1) T0

Take2 returns the first of the two provided arguments, discarding the second.

Deprecated: use Get1of2 instead.

Example
package main

import (
	"fmt"
	"net"

	"github.com/goaux/results"
)

func main() {
	fmt.Println(results.Take2(
		results.May2(net.SplitHostPort("example.com:80")).Or("localhost", "80"),
	))
}
Output:

example.com

func Take3 deprecated added in v1.4.0

func Take3[T0, T1, T2 any](a T0, _ T1, _ T2) T0

Take3 returns the first of the three provided arguments, discarding the other two.

Deprecated: use Get1of3 instead.

Example
package main

import (
	"fmt"

	"github.com/goaux/results"
)

func main() {
	example := func() (x, y, z int) { return 11, 22, 33 }
	fmt.Println(results.Take3(example()))
}
Output:

11

func TypeAs added in v1.9.0

func TypeAs[T any](v any) (value T, ok bool)

TypeAs returns the result of type assertions. This is a function, so it is addressable.

value, ok := v.(T)
Example
package main

import (
	"fmt"

	"github.com/goaux/results"
)

func main() {
	asStr := results.TypeAs[string]
	asInt := results.TypeAs[int]
	fmt.Println(asStr("hello"))
	fmt.Println(asInt("hello"))
}
Output:

hello true
0 false

Types

type Maybe

type Maybe interface {
	// Values returns the stored values.
	Values() []any

	// Error returns the error
	Error() error

	// HasError returns true if there's an error, false otherwise
	HasError() bool
}

Maybe is the interface for Maybe1, Maybe2 and Maybe3.

type Maybe1

type Maybe1[T any] struct {
	V0  T
	Err error
}

Maybe1 holds a value and an error

Example
package main

import (
	"fmt"
	"strconv"

	"github.com/goaux/results"
)

var _ results.Maybe = results.Maybe1[any]{}

func main() {
	v := results.May1(strconv.Atoi("999")).Or(42)
	fmt.Println(v)

	v = results.May1(strconv.Atoi("999")).OrPanic()
	fmt.Println(v)

	v = results.May1(strconv.Atoi("NaN")).Or(42)
	fmt.Println(v)

	v = results.May1(strconv.Atoi("NaN")).OrFunc(func() int { return 80 })
	fmt.Println(v)
}
Output:

999
999
42
80

func May1

func May1[T any](v0 T, err error) Maybe1[T]

May1 creates a Maybe1 from a v0 and an error

func (Maybe1[T]) Error

func (m Maybe1[T]) Error() error

Error returns the error

func (Maybe1[T]) HasError

func (m Maybe1[T]) HasError() bool

HasError returns true if there's an error, false otherwise

func (Maybe1[T]) Or

func (m Maybe1[T]) Or(defaultValue T) T

Or returns the default value if there's an error, otherwise returns the stored value

func (Maybe1[T]) OrFunc added in v1.2.0

func (m Maybe1[T]) OrFunc(f func() T) T

OrFunc returns the result of the function if there is an error, otherwise it returns the stored value. The function f is called only if there is an error.

func (Maybe1[T]) OrPanic

func (m Maybe1[T]) OrPanic() T

OrPanic panics if there's an error, otherwise returns the stored value

func (Maybe1[T]) Values

func (m Maybe1[T]) Values() []any

Values returns the stored value.

type Maybe2

type Maybe2[T0, T1 any] struct {
	V0  T0
	V1  T1
	Err error
}

Maybe2 holds two values and an error

Example
package main

import (
	"fmt"
	"net"

	"github.com/goaux/results"
)

var _ results.Maybe = results.Maybe2[any, any]{}

func main() {
	host, port := results.May2(net.SplitHostPort("example.com:80")).Or("localhost", "80")
	fmt.Println(host, port)

	host, port = results.May2(net.SplitHostPort("example.com:80")).OrPanic()
	fmt.Println(host, port)

	host, port = results.May2(net.SplitHostPort("error")).Or("localhost", "80")
	fmt.Println(host, port)

	host, port = results.May2(net.SplitHostPort("error")).OrFunc(
		func() (string, string) { return "example.com", "8080" },
	)
	fmt.Println(host, port)
}
Output:

example.com 80
example.com 80
localhost 80
example.com 8080

func May2

func May2[T0, T1 any](v0 T0, v1 T1, err error) Maybe2[T0, T1]

May2 creates a Maybe2 from two values and an error

func (Maybe2[T0, T1]) Error

func (m Maybe2[T0, T1]) Error() error

Error returns the error

func (Maybe2[T0, T1]) HasError

func (m Maybe2[T0, T1]) HasError() bool

HasError returns true if there's an error, false otherwise

func (Maybe2[T0, T1]) Or

func (m Maybe2[T0, T1]) Or(d0 T0, d1 T1) (T0, T1)

Or returns the default values if there's an error, otherwise returns the stored values

func (Maybe2[T0, T1]) OrFunc added in v1.2.0

func (m Maybe2[T0, T1]) OrFunc(f func() (T0, T1)) (T0, T1)

OrFunc returns the result of the function if there is an error, otherwise it returns the stored value. The function f is called only if there is an error.

func (Maybe2[T0, T1]) OrPanic

func (m Maybe2[T0, T1]) OrPanic() (T0, T1)

OrPanic panics if there's an error, otherwise returns the stored values

func (Maybe2[T0, T1]) Values

func (m Maybe2[T0, T1]) Values() []any

Values returns the stored values.

type Maybe3

type Maybe3[T0, T1, T2 any] struct {
	V0  T0
	V1  T1
	V2  T2
	Err error
}

Maybe3 holds three values and an error

Example
package main

import (
	"fmt"

	"github.com/goaux/results"
)

var _ results.Maybe = results.Maybe3[any, any, any]{}

func main() {
	example := func(string) (x, y, z int, err error) { return 8, 7, 6, nil }
	x, y, z := results.May3(example("8,7,6")).Or(1, 1, 1)
	fmt.Println(x, y, z)

	x, y, z = results.May3(example("8,7,6")).OrPanic()
	fmt.Println(x, y, z)

	example = func(string) (x, y, z int, err error) { return 0, 0, 0, fmt.Errorf("invalid") }
	x, y, z = results.May3(example("error")).Or(1, 1, 1)
	fmt.Println(x, y, z)

	example = func(string) (x, y, z int, err error) { return 0, 0, 0, fmt.Errorf("invalid") }
	x, y, z = results.May3(example("error")).OrFunc(
		func() (int, int, int) { return 2, 3, 4 },
	)
	fmt.Println(x, y, z)
}
Output:

8 7 6
8 7 6
1 1 1
2 3 4

func May3

func May3[T0, T1, T2 any](v0 T0, v1 T1, v2 T2, err error) Maybe3[T0, T1, T2]

May3 creates a Maybe3 from three values and an error

func (Maybe3[T0, T1, T2]) Error

func (m Maybe3[T0, T1, T2]) Error() error

Error returns the error

func (Maybe3[T0, T1, T2]) HasError

func (m Maybe3[T0, T1, T2]) HasError() bool

HasError returns true if there's an error, false otherwise

func (Maybe3[T0, T1, T2]) Or

func (m Maybe3[T0, T1, T2]) Or(d0 T0, d1 T1, d2 T2) (T0, T1, T2)

Or returns the default values if there's an error, otherwise returns the stored values

func (Maybe3[T0, T1, T2]) OrFunc added in v1.2.0

func (m Maybe3[T0, T1, T2]) OrFunc(f func() (T0, T1, T2)) (T0, T1, T2)

OrFunc returns the result of the function if there is an error, otherwise it returns the stored value. The function f is called only if there is an error.

func (Maybe3[T0, T1, T2]) OrPanic

func (m Maybe3[T0, T1, T2]) OrPanic() (T0, T1, T2)

OrPanic panics if there's an error, otherwise returns the stored values

func (Maybe3[T0, T1, T2]) Values

func (m Maybe3[T0, T1, T2]) Values() []any

Values returns the stored values.

type True added in v1.5.0

type True interface {
	// Values returns the stored values.
	Values() []any

	// IsOK returns the value of OK.
	IsOK() bool
}

True is the interface for True1 and True2.

type True1 added in v1.5.0

type True1[T any] struct {
	V0 T
	OK bool
}

True1 holds a value and a bool.

Example
package main

import (
	"fmt"
	"os"

	"github.com/goaux/results"
)

func main() {
	os.Setenv("EXAMPLE", "example")
	os.Unsetenv("EXAMPLE2")
	fmt.Println(results.If1(os.LookupEnv("EXAMPLE")).Or("fallback"))
	fmt.Println(results.If1(os.LookupEnv("EXAMPLE")).OrPanic("undefined"))
	fmt.Println(results.If1(os.LookupEnv("EXAMPLE2")).Or("fallback"))
	fmt.Println(results.If1(os.LookupEnv("EXAMPLE2")).OrFunc(func() string { return "fallback" }))
}
Output:

example
example
fallback
fallback

func If1 added in v1.5.0

func If1[T any](v0 T, ok bool) True1[T]

If1 creates a True1 from v0 and ok.

func (True1[T]) IsOK added in v1.5.0

func (t True1[T]) IsOK() bool

IsOK returns t.OK.

func (True1[T]) Or added in v1.5.0

func (t True1[T]) Or(defaultValue T) T

Or returns t.V0 if t.OK = true, otherwise defaultValue.

func (True1[T]) OrFunc added in v1.5.0

func (t True1[T]) OrFunc(f func() T) T

OrFunc returns t.V0 if t.OK = true, otherwise the result of calling f.

func (True1[T]) OrPanic added in v1.5.0

func (t True1[T]) OrPanic(msg any) T

OrPanic returns t.V0 if t.OK = true, otherwise calling [panic](msg).

func (True1[T]) Values added in v1.5.0

func (t True1[T]) Values() []any

Values returns the stored value.

type True2 added in v1.5.0

type True2[T0, T1 any] struct {
	V0 T0
	V1 T1
	OK bool
}

True2 holds values and a bool.

Example
package main

import (
	"fmt"

	"github.com/goaux/results"
)

func main() {
	fmt.Println(results.If2("example", 42, true).Or("fallback", 99))
	fmt.Println(results.If2("example", 42, true).OrPanic("undefined"))
	fmt.Println(results.If2("example", 42, false).Or("fallback", 99))
	fmt.Println(results.If2("example", 42, false).OrFunc(func() (string, int) { return "fallback", 99 }))
}
Output:

example 42
example 42
fallback 99
fallback 99

func If2 added in v1.5.0

func If2[T0, T1 any](v0 T0, v1 T1, ok bool) True2[T0, T1]

If2 creates a True2 from v0, v1 and ok.

func (True2[T0, T1]) IsOK added in v1.5.0

func (t True2[T0, T1]) IsOK() bool

IsOK returns t.OK.

func (True2[T0, T1]) Or added in v1.5.0

func (t True2[T0, T1]) Or(v0 T0, v1 T1) (T0, T1)

Or returns t.V0 and t.V1 if t.OK = true, otherwise v0, v1.

func (True2[T0, T1]) OrFunc added in v1.5.0

func (t True2[T0, T1]) OrFunc(f func() (T0, T1)) (T0, T1)

OrFunc returns t.V0 and t.V1 if t.OK = true, otherwise the result of calling f.

func (True2[T0, T1]) OrPanic added in v1.5.0

func (t True2[T0, T1]) OrPanic(msg any) (T0, T1)

OrPanic returns t.V0 and t.V1 if t.OK = true, otherwise calling [panic](msg).

func (True2[T0, T1]) Values added in v1.5.0

func (t True2[T0, T1]) Values() []any

Values returns the stored value.

Jump to

Keyboard shortcuts

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