either

package
v0.1.3 Latest Latest
Warning

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

Go to latest
Published: Feb 21, 2026 License: MIT Imports: 1 Imported by: 0

Documentation

Overview

Package either provides the Either[L, R] type for Go.

Either[L, R] represents a value that is either Left(L) or Right(R). Unlike Result[T], neither side implies success or failure both Left and Right are valid, meaningful values.

Either vs Result

Use Result[T] when one path is success and the other is an error. Use Either[L, R] when both paths carry domain values of different types.

// Result: Ok or Err
result.Ok(user) vs result.Err(ErrNotFound)

// Either: Two different valid results
either.Left[User, Guest](user) vs either.Right[User, Guest](guest)

Performance

Either[L, R] is a plain struct no heap allocation for the wrapper. Both left and right values are stored inline.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ContainsLeft

func ContainsLeft[L comparable, R any](e Either[L, R], target L) bool

ContainsLeft returns true if the Either is Left and the value equals target.

func ContainsRight

func ContainsRight[L any, R comparable](e Either[L, R], target R) bool

ContainsRight returns true if the Either is Right and the value equals target.

func ErrRight

func ErrRight[L any](e Either[L, error]) error

ErrRight returns the Right value if it implements error, otherwise nil. Useful for error checking when R = error.

if err := either.ErrRight(e); err != nil { ... }

func Fold

func Fold[L, R, T any](e Either[L, R], leftFn func(L) T, rightFn func(R) T) T

Fold applies leftFn to Left or rightFn to Right, collapsing the Either into a single value of type T. This is the primary way to consume an Either.

msg := either.Fold(e,
    func(age int) string { return fmt.Sprintf("age: %d", age) },
    func(err string) string { return "error: " + err },
)

func IsErr

func IsErr[L any](e Either[L, error], target error) bool

IsErr returns true if the Either is Right and the error matches target using errors.Is semantics.

either.IsErr(e, ErrNotFound)

func LeftOr

func LeftOr[T any](e Either[T, error]) (T, error)

LeftToResult converts Either[T, error] to a Result using the right side as error. Panics if R is not error — use ToResult for Either[T, error].

func Merge

func Merge[T any](e Either[T, T]) T

Merge collapses Either[T, T] into a T. Works only when both sides have the same type.

either.Left[int, int](42).Merge()  → 42
either.Right[int, int](99).Merge() → 99

func Partition

func Partition[L, R any](eithers []Either[L, R]) (lefts []L, rights []R)

Partition splits a slice of Either values into left and right slices.

lefts, rights := either.Partition(eithers)

func ToResult

func ToResult[T any](e Either[T, error]) (T, error)

ToResult converts Either[T, error] into a (T, error) tuple. Left(v) → (v, nil), Right(e) → (zero, e). Compatible with result.Of for further chaining.

r := result.Of(either.ToResult(e))

Types

type Either

type Either[L, R any] struct {
	// contains filtered or unexported fields
}

Either[L, R] holds either a Left value of type L or a Right value of type R. Exactly one side is always populated.

Zero value is NOT VALID always use Left() or Right() constructors.

func FlatMapLeft

func FlatMapLeft[L, R, L2 any](e Either[L, R], f func(L) Either[L2, R]) Either[L2, R]

FlatMapLeft applies f to the Left value if Left. f returns a new Either, allowing chaining. Returns Right unchanged.

either.FlatMapLeft(e, func(n int) Either[string, Error] {
    if n < 0 { return either.Right[string, Error](ErrNegative) }
    return either.Left[string, Error](strconv.Itoa(n))
})

func FlatMapRight

func FlatMapRight[L, R, R2 any](e Either[L, R], f func(R) Either[L, R2]) Either[L, R2]

FlatMapRight applies f to the Right value if Right. Returns Left unchanged.

func FromResult

func FromResult[T any, E interface{ Error() string }](value T, err error) Either[T, error]

FromResult converts a Result[T] into an Either[T, error]. Ok(v) → Left(v), Err(e) → Right(e).

Convention mirrors Result semantics: Left = success, Right = error.

func Left

func Left[L, R any](value L) Either[L, R]

Left returns an Either containing a left value of type L.

e := either.Left[User, string](user)

func MapBoth

func MapBoth[L, R, L2, R2 any](e Either[L, R], leftFn func(L) L2, rightFn func(R) R2) Either[L2, R2]

MapBoth applies leftFn to Left or rightFn to Right, returning a new Either with both sides potentially transformed.

either.MapBoth(e,
    func(n int) int { return n * 2 },
    func(s string) string { return strings.ToUpper(s) },
)

func MapLeft

func MapLeft[L, R, L2 any](e Either[L, R], f func(L) L2) Either[L2, R]

MapLeft applies f to the Left value if Left, returning a new Either. Returns Right unchanged.

either.MapLeft(e, func(n int) int { return n * 2 })

func MapRight

func MapRight[L, R, R2 any](e Either[L, R], f func(R) R2) Either[L, R2]

MapRight applies f to the Right value if Right, returning a new Either. Returns Left unchanged.

either.MapRight(e, func(s string) int { return len(s) })
func Right[L, R any](value R) Either[L, R]

Right returns an Either containing a right value of type R.

e := either.Right[User, string]("guest")

func (Either[L, R]) IfLeft

func (e Either[L, R]) IfLeft(f func(L)) Either[L, R]

IfLeft calls f with the Left value if Left. Returns e unchanged for chaining.

e.IfLeft(func(n int) { log.Println("left:", n) })

func (Either[L, R]) IfRight

func (e Either[L, R]) IfRight(f func(R)) Either[L, R]

IfRight calls f with the Right value if Right. Returns e unchanged for chaining.

func (Either[L, R]) IsLeft

func (e Either[L, R]) IsLeft() bool

IsLeft reports whether the Either contains a Left value.

func (Either[L, R]) IsLeftAnd

func (e Either[L, R]) IsLeftAnd(f func(L) bool) bool

IsLeftAnd returns true if the Either is Left and f(value) returns true.

e.IsLeftAnd(func(n int) bool { return n > 0 })

func (Either[L, R]) IsRight

func (e Either[L, R]) IsRight() bool

IsRight reports whether the Either contains a Right value.

func (Either[L, R]) IsRightAnd

func (e Either[L, R]) IsRightAnd(f func(R) bool) bool

IsRightAnd returns true if the Either is Right and f(value) returns true.

func (Either[L, R]) Swap

func (e Either[L, R]) Swap() Either[R, L]

Swap returns a new Either with Left and Right sides exchanged.

either.Left[int, string](42).Swap() → Right[string, int](42)

func (Either[L, R]) Tap

func (e Either[L, R]) Tap(leftFn func(L), rightFn func(R)) Either[L, R]

Tap calls leftFn or rightFn depending on which side is populated. Returns e unchanged for chaining.

e.Tap(
    func(n int) { log.Println("left:", n) },
    func(s string) { log.Println("right:", s) },
)

func (Either[L, R]) UnwrapLeft

func (e Either[L, R]) UnwrapLeft() L

UnwrapLeft returns the Left value. Panics if the Either is Right.

func (Either[L, R]) UnwrapLeftOr

func (e Either[L, R]) UnwrapLeftOr(defaultValue L) L

UnwrapLeftOr returns the Left value, or defaultValue if Right.

age := e.UnwrapLeftOr(0)

func (Either[L, R]) UnwrapLeftOrElse

func (e Either[L, R]) UnwrapLeftOrElse(f func(R) L) L

UnwrapLeftOrElse returns the Left value, or calls f and returns its result if Right.

func (Either[L, R]) UnwrapRight

func (e Either[L, R]) UnwrapRight() R

UnwrapRight returns the Right value. Panics if the Either is Left.

func (Either[L, R]) UnwrapRightOr

func (e Either[L, R]) UnwrapRightOr(defaultValue R) R

UnwrapRightOr returns the Right value, or defaultValue if Left.

func (Either[L, R]) UnwrapRightOrElse

func (e Either[L, R]) UnwrapRightOrElse(f func(L) R) R

UnwrapRightOrElse returns the Right value, or calls f and returns its result if Left.

Jump to

Keyboard shortcuts

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