opera

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Jan 23, 2026 License: MIT Imports: 10 Imported by: 0

README

opera

Go Version Test Status

opera - Option, Error handling, Result, and Async, a library that brings better error handling and async programming to Golang.

Acknowledgments

This library was inspired by two excellent projects:

  • eh, which introduced the idea of Rust‑like error handling in Go.
  • mo, from which the Do notation and Option marshaling into/out of values were adapted.

Many thanks to their authors for the inspiration.

Use Case

Error Handling with opera

Checking a username and password often involves nested if statements and explicit error handling, for example:

func checkLogin(user, password string) (bool, error) {
     ctx, _ := context.Background()
 
    // unpack result in the old way
    u, err := gorm.G[model.User](db).
        Where(gen.User.Username.Eq(user)).
        First(ctx)
    if err != nil {
        // return false if user not found
        if errors.Is(err, gorm.ErrRecordNotFound) {
            return false, nil
        }
        // propagate other errors
        return false, err
    }

     if bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password)) != nil {
        return false, nil
    }

     return true, nil
}

With opera Do notation, you can safely unwrap the result of a failable function without repeatedly writing if val, err := fn(); err != nil. The output of a function can be safely produced with Result.Yield(), and fast‑fail is implicitly handled by Do notation. No explicit manipulation on error is needed in the context of Do notation. :

func(user, password string) (ok bool, err error) {
    // use `Do` notation
    return opera.Do(func() bool {
        ctx, _ := context.Background()

        // get user with `Do` notation and `Result` without `if`
        // fail fast to `Do` when `err` occurs
        user := opera.Try(gorm.G[model.User](db).
            Where(gen.User.Username.Eq(user)).
            First(ctx)).Yield()

        // fail fast also applies to `Option` type
        pwd := opera.MaybeNilPtr(user.Password).Yield()

        // also fail fast if seen `ErrMismatchedHashAndPassword`
        opera.Must0(bcrypt.CompareHashAndPassword([]byte(pwd), []byte(password)))

        // login success
        return true
    }).
        // conditionally recover if certain errors are met 
        CatchIs(gorm.ErrRecordNotFound, false).
        CatchIs(bcrypt.ErrMismatchedHashAndPassword, false).
        Get() // unpack to `(T, error)` in the end
}
Performance Caveat

The design of how this library achieves fail‑fast error handling may introduce little performance overhead. For reference, below is a simple benchmark result of two test cases in the project comparing the same operation with and without Do.

cpu: AMD Ryzen 9 8945HS w/ Radeon 780M Graphics
BenchmarkDoAndGet/ErrFromGet-16              6267090           188.3 ns/op         128 B/op           3 allocs/op
BenchmarkDoAndGet/ErrFromDo-16               6167328           196.9 ns/op         128 B/op           3 allocs/op
Concurrency with opera Async

Async in opera provides a clean way to organize structured concurrency tasks without manually managing goroutines, channels, or synchronization primitives.

func(ctx context.Context, q *gorm.DB, p Params) error {
    return opera.Do(func () any {
        // ctx `Done` of parent also cancels tasks fired by opera.Async and unblocks opera.Await
        countTask := opera.Async(ctx, func(ctx context.Context) opera.Result[int64] {
            return opera.Try(q.Count(ctx, "*"))
        })
        dataTask := opera.Async(ctx, func(ctx context.Context) opera.Result[[]T] {
            size := p.Size.Or(20)
            offset := (p.Page.Or(1) - 1) * size
            q.Offset(offset).Limit(size)
            return opera.Try(q.Find(ctx))
        })
        // Getting results of two async tasks in one line
        count, data := opera.Await(ctx, countTask).Yield(), opera.Await(ctx, dataTask).Yield()
        return nil
    }).Err()
}

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrAny = errors.New("[opera] any error sentinel")

ErrAny is a sentinel error value used to match any error.

View Source
var ErrAsyncAllOpsFailed = errors.New("all async operations failed")
View Source
var ErrAsyncArgumentNotChannelOfResult = errors.New("argument is not a channel of Result")
View Source
var ErrAsyncAwaitedValueCastError = errors.New("awaited value cast error")
View Source
var ErrAsyncChannelClosed = errors.New("channel closed")
View Source
var ErrInputCastFailed = errors.New("cast input failed")
View Source
var ErrNoSuchElement = errors.New("no such element")
View Source
var ErrPredicateFalse = errors.New("predicate returns false")
View Source
var ErrResultCastFailed = errors.New("inner value type cast failed")

Functions

func Async

func Async[T any](ctx context.Context, fn Thunk[T]) <-chan Result[T]

Async runs fn(ctx) (T, error) in a goroutine and returns a channel for its Result.

func Empty

func Empty[T any]() T

Empty is a helper function that returns the zero value of type T.

func IsEmpty

func IsEmpty[T any](val T) bool

IsEmpty checks if the given value is the zero value of its type. It first tries to handle common types explicitly for performance, then falls back to using reflection.

func Must

func Must[T any](val T, err error) T

Must extracts the value from a Result, bails out if there is an error.

func MustCast

func MustCast[T any](val any) T

MustCast extracts the value from a successful Result of a type cast, bails out if there is an error.

func MustHave

func MustHave[T any](val T, ok bool) T

MustHave extracts the value from a Result, bail out if the boolean flag is false.

func MustPass

func MustPass(err error)

MustPass bails out if there is an error.

func MustTrue

func MustTrue(ok bool)

MustTrue bails out if the boolean flag is false.

func Step

func Step[T any](flow *workflow, work func() Result[T], rollback func(error)) T

Step executes a workflow step with rollback support along with an workflow instance. If the step returns an error, all registered rollbacks are executed in reverse order. Caveat: `opera.Step` yield value of `Result` directly like `opera.Must`, . Example:

opera.Do(func() {
    flow := opera.Workflow()
    result1 := opera.Step(flow, step1, rollback1)
    result2 := opera.Step(flow, step2, rollback2)
    ...
})

func Workflow

func Workflow() *workflow

Workflow creates a new workflow instance. Rollbacks are registered per step and executed in reverse order if any step fails. Example:

opera.Do(func() {
    flow := opera.Workflow()
    result1 := opera.Step(flow, step1, rollback1)
    result2 := opera.Step(flow, step2, rollback2)
    ...
})

Types

type Option

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

Option is a container for an optional value of type T. If value exists, Option is of type Some. If the value is absent, Option is of type None.

func CastOption

func CastOption[U any, T any](opt Option[T]) Option[U]

CastOption tries to convert Option[T] to Option[U] and returns None if conversion fails.

func MapOption added in v0.2.0

func MapOption[T, U any](opt Option[T], fn func(T) U) Option[U]

MapOption applies a function to the value inside an Option[T] if it is Some, returning an Option[U].

func MayCast

func MayCast[T any](val any) Option[T]

MayCast tries to cast val to type T and returns Some if successful, or None otherwise.

func MayHave

func MayHave[T any](val T, ok bool) Option[T]

MayHave creates an Option from a value and a boolean flag.

func MayLookUp added in v0.1.2

func MayLookUp[T any](m map[string]T, key string) Option[T]

MayLookUp attempts to retrieve a value from a map by key, returning an Option.

func MaybeEmpty

func MaybeEmpty[T any](val T) Option[T]

MaybeEmpty builds a Some Option when val is not empty, or None.

func MaybeNilPtr

func MaybeNilPtr[T any](val *T) Option[T]

MaybeNilPtr builds a Some Option when val is not nil, or None.

func None

func None[T any]() Option[T]

None creates an Option without a value.

func Some

func Some[T any](val T) Option[T]

Some creates an Option with a value.

func (Option[T]) Chain

func (o Option[T]) Chain(mapper func(value T) Option[T]) Option[T]

Chain executes the mapper function if value is present or returns None if absent.

func (Option[T]) Equal

func (o Option[T]) Equal(other Option[T]) bool

Equal compares two Option[T] instances for equality

func (Option[T]) Get

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

Get returns value and presence.

func (*Option[T]) GobDecode

func (o *Option[T]) GobDecode(data []byte) error

GobDecode implements the gob.GobDecoder interface.

func (Option[T]) GobEncode

func (o Option[T]) GobEncode() ([]byte, error)

GobEncode implements the gob.GobEncoder interface.

func (Option[T]) IsNone

func (o Option[T]) IsNone() bool

IsNone returns false when value is present.

func (Option[T]) IsSome

func (o Option[T]) IsSome() bool

IsSome is an alias to IsPresent.

func (Option[T]) IsZero

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

IsZero assists `omitzero` tag introduced in Go 1.24

func (Option[T]) Map

func (o Option[T]) Map(fn func(value T) T) Option[T]

Map executes the mapper function if value is present or returns None if absent.

func (Option[T]) MarshalBinary

func (o Option[T]) MarshalBinary() ([]byte, error)

MarshalBinary is the interface implemented by an object that can marshal itself into a binary form.

func (Option[T]) MarshalJSON

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

MarshalJSON encodes Option into json. Go 1.20+ relies on the IsZero method when the `omitempty` tag is used unless a custom MarshalJSON method is defined. Then the IsZero method is ignored. current best workaround is to instead use `omitzero` tag with Go 1.24+

func (Option[T]) MarshalText

func (o Option[T]) MarshalText() ([]byte, error)

MarshalText implements the encoding.TextMarshaler interface.

func (Option[T]) Or

func (o Option[T]) Or(fallback T) T

Or returns value if present or default value.

func (Option[T]) OrElse

func (o Option[T]) OrElse(fn func() Option[T]) Option[T]

OrElse executes the function if value is absent or returns the original Option if present.

func (Option[T]) OrEmpty

func (o Option[T]) OrEmpty() T

OrEmpty returns value if present or empty value.

func (*Option[T]) Scan

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

Scan implements the SQL sql.Scanner interface.

func (Option[T]) Tap

func (o Option[T]) Tap(fn func(value T)) Option[T]

Tap executes the function if value is present and returns the original Option.

func (Option[T]) TapNone

func (o Option[T]) TapNone(fn func()) Option[T]

TapNone executes the function if value is absent and returns the original Option.

func (Option[T]) ToAny

func (o Option[T]) ToAny() Option[any]

func (Option[T]) ToPointer

func (o Option[T]) ToPointer() *T

ToPointer returns value if present or a nil pointer.

func (Option[T]) ToResult

func (o Option[T]) ToResult() Result[T]

ToResult converts Option to Result, returning Err if value is absent.

func (*Option[T]) UnmarshalBinary

func (o *Option[T]) UnmarshalBinary(data []byte) error

UnmarshalBinary is the interface implemented by an object that can unmarshal a binary representation of itself.

func (*Option[T]) UnmarshalJSON

func (o *Option[T]) UnmarshalJSON(b []byte) error

UnmarshalJSON decodes Option from json.

func (*Option[T]) UnmarshalText

func (o *Option[T]) UnmarshalText(data []byte) error

UnmarshalText implements the encoding.TextUnmarshaler interface.

func (Option[T]) Value

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

Value implements the driver Valuer interface.

func (Option[T]) Yield

func (o Option[T]) Yield() T

Yield yields value if present or bail out instead. If under `Do` notation, an `ErrOptionNoSuchElement` will be caught.

type Result

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

Result represents a value that may either be a success (Ok) or a failure (Err).

func Await

func Await[T any](ctx context.Context, ch <-chan Result[T]) Result[T]

Await blocks receiving a Result[T] or context cancellation. If the channel is nil, it returns Ok result with empty T value immediately.

func AwaitAll

func AwaitAll[T any](ctx context.Context, chans ...any) Result[[]T]

AwaitAll waits for all channels and returns collected values or first error. The order of returned values corresponds to the order of input channels. If a channel is nil, the corresponding value will be an empty T. Use AwaitAllSettled to collect all results including errors.

func AwaitAllSettled

func AwaitAllSettled[T any](ctx context.Context, chans ...any) []Result[T]

AwaitAllSettled awaits all channels and returns their results as a slice. The order of returned results corresponds to the order of input channels. If a channel is nil, the corresponding result will be an Ok with empty T. Use AwaitAll to return early on first error.

func AwaitAllSettledT

func AwaitAllSettledT[T any](ctx context.Context, chans ...<-chan Result[T]) []Result[T]

AwaitAllSettledT is a type-safe wrapper for AwaitAllSettled for homogeneous channels.

func AwaitAllT

func AwaitAllT[T any](ctx context.Context, chans ...<-chan Result[T]) Result[[]T]

AwaitAllT is a type-safe wrapper for AwaitAll for homogeneous channels.

func AwaitFirst

func AwaitFirst[T any](ctx context.Context, chans ...any) Result[Tuple[T, int]]

AwaitFirst waits for the first successful Result from the provided channels errors are ignored unless all operations are failed. There may be [randomness](https://go.dev/tour/concurrency/5) if multiple channels are ready simultaneously.

func AwaitFirstT

func AwaitFirstT[T any](ctx context.Context, chans ...<-chan Result[T]) Result[Tuple[T, int]]

AwaitFirstT is a type-safe wrapper for AwaitFirst for homogeneous channels.

func AwaitZip

func AwaitZip[T1, T2 any](
	ctx context.Context,
	ch1 <-chan Result[T1],
	ch2 <-chan Result[T2],
) Result[Tuple[T1, T2]]

AwaitZip awaits 2 channels and returns their results as a tuple.

func AwaitZip3

func AwaitZip3[T1, T2, T3 any](
	ctx context.Context,
	ch1 <-chan Result[T1],
	ch2 <-chan Result[T2],
	ch3 <-chan Result[T3],
) Result[Tuple3[T1, T2, T3]]

AwaitZip3 awaits 3 channels and returns their results as a tuple.

func AwaitZip4

func AwaitZip4[T1, T2, T3, T4 any](
	ctx context.Context,
	ch1 <-chan Result[T1],
	ch2 <-chan Result[T2],
	ch3 <-chan Result[T3],
	ch4 <-chan Result[T4],
) Result[Tuple4[T1, T2, T3, T4]]

AwaitZip4 awaits 4 channels and returns their results as a tuple.

func AwaitZip5

func AwaitZip5[T1, T2, T3, T4, T5 any](
	ctx context.Context,
	ch1 <-chan Result[T1],
	ch2 <-chan Result[T2],
	ch3 <-chan Result[T3],
	ch4 <-chan Result[T4],
	ch5 <-chan Result[T5],
) Result[Tuple5[T1, T2, T3, T4, T5]]

AwaitZip5 awaits 5 channels and returns their results as a tuple.

func AwaitZip6

func AwaitZip6[T1, T2, T3, T4, T5, T6 any](
	ctx context.Context,
	ch1 <-chan Result[T1],
	ch2 <-chan Result[T2],
	ch3 <-chan Result[T3],
	ch4 <-chan Result[T4],
	ch5 <-chan Result[T5],
	ch6 <-chan Result[T6],
) Result[Tuple6[T1, T2, T3, T4, T5, T6]]

AwaitZip6 awaits 6 channels and returns their results as a tuple.

func AwaitZip7

func AwaitZip7[T1, T2, T3, T4, T5, T6, T7 any](
	ctx context.Context,
	ch1 <-chan Result[T1],
	ch2 <-chan Result[T2],
	ch3 <-chan Result[T3],
	ch4 <-chan Result[T4],
	ch5 <-chan Result[T5],
	ch6 <-chan Result[T6],
	ch7 <-chan Result[T7],
) Result[Tuple7[T1, T2, T3, T4, T5, T6, T7]]

AwaitZip7 awaits 7 channels and returns their results as a tuple.

func AwaitZip8

func AwaitZip8[T1, T2, T3, T4, T5, T6, T7, T8 any](
	ctx context.Context,
	ch1 <-chan Result[T1],
	ch2 <-chan Result[T2],
	ch3 <-chan Result[T3],
	ch4 <-chan Result[T4],
	ch5 <-chan Result[T5],
	ch6 <-chan Result[T6],
	ch7 <-chan Result[T7],
	ch8 <-chan Result[T8],
) Result[Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]

AwaitZip8 awaits 8 channels and returns their results as a tuple.

func AwaitZip9

func AwaitZip9[T1, T2, T3, T4, T5, T6, T7, T8, T9 any](
	ctx context.Context,
	ch1 <-chan Result[T1],
	ch2 <-chan Result[T2],
	ch3 <-chan Result[T3],
	ch4 <-chan Result[T4],
	ch5 <-chan Result[T5],
	ch6 <-chan Result[T6],
	ch7 <-chan Result[T7],
	ch8 <-chan Result[T8],
	ch9 <-chan Result[T9],
) Result[Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]

AwaitZip9 awaits 9 channels and returns their results as a tuple.

func CastResult

func CastResult[U, T any](res Result[T]) Result[U]

CastResult attempts to convert the value inside a Result[T] to type U.

func Do

func Do[T any](fn func() T) (result Result[T])

Do executes a function within a monadic context, capturing any errors that occur. If the function executes successfully, its result is wrapped in a successful Result. If the function panics (indicating a failure), the panic is caught and converted into an error Result.

func Err

func Err[T any](err error) Result[T]

Err constructs a failed Result from an error.

func MapResult added in v0.2.0

func MapResult[T, U any](res Result[T], fn func(T) U) Result[U]

MapResult applies a function to the value inside a Result[T] if it is successful, returning a Result[U].

func Ok

func Ok[T any](val T) Result[T]

Ok constructs a successful Result from a value.

func Scoped

func Scoped[T, R any](
	acquire func() Result[T],
	use func(T) Result[R],
	release func(T),
) Result[R]

/ Scoped manages a resource within a monadic context, ensuring that the resource is properly released after use.

func Try

func Try[T any](val T, err error) Result[T]

Try constructs a Result from a value and an error.

func TryCast

func TryCast[T any](val any) Result[T]

TryCast attempts to cast a value to type T, returning a Result.

func TryHave

func TryHave[T any](val T, ok bool) Result[T]

TryHave constructs a Result from a value and a boolean flag.

func TryIf

func TryIf(ok bool) Result[Unit]

TryIf constructs a Result with no value from just a boolean flag.

func TryLookUp added in v0.1.2

func TryLookUp[T any](m map[string]T, key string) Result[T]

TryLookUp attempts to retrieve a value from a map by key, returning a Result.

func TryPass

func TryPass(err error) Result[Unit]

TryPass constructs a Result with no value from just an error.

func (Result[T]) Catch

func (r Result[T]) Catch(fn func(error) Result[T]) Result[T]

Catch applies a function that returns a Result to the error if the Result is Err, otherwise returns the Ok unchanged.

func (Result[T]) CatchIs

func (r Result[T]) CatchIs(pred error, fallback T) Result[T]

CatchIs tests the error using errors.Is, and if it matches, recovers by applying a handler function to produce a value. opera.AnyError can be used to match any error.

func (Result[T]) CatchString

func (r Result[T]) CatchString(contains string, fallback T) Result[T]

CatchString tests if the error message contains a substring, and if it does, recovers by providing a fallback value.

func (Result[T]) Chain

func (r Result[T]) Chain(fn func(T) Result[T]) Result[T]

Chain applies a function that returns a Result to the value if the Result is Ok, otherwise returns the Err unchanged.

func (Result[T]) Err

func (r Result[T]) Err() error

Err extracts the error from a Result, nil if there is no error.

func (Result[T]) Get

func (r Result[T]) Get() (T, error)

Get extracts the value and error from a Result.

func (Result[T]) IsErr

func (r Result[T]) IsErr() bool

Ok creates a successful Result.

func (Result[T]) IsOk

func (r Result[T]) IsOk() bool

IsOk returns true if the Result is Ok.

func (Result[T]) Map

func (r Result[T]) Map(fn func(T) T) Result[T]

Map applies a function to the value if the Result is Ok, otherwise returns the Err unchanged.

func (Result[T]) MapErr

func (r Result[T]) MapErr(fn func(error) error) Result[T]

MapErr applies a function to the error if the Result is Err, otherwise returns the Ok unchanged.

func (Result[T]) MapErrIs

func (r Result[T]) MapErrIs(pred error, other error) Result[T]

MapErrIs tests the error using errors.Is, and if it matches, replaces it with another error. opera.ErrAny can be used to match any error.

func (Result[T]) MapErrorString

func (r Result[T]) MapErrorString(contains string, other error) Result[T]

MapErrorString tests if the error message contains a substring, and if it does, replaces it with another error.

func (Result[T]) Or

func (r Result[T]) Or(fallback T) T

Or returns the value if the Result is Ok, otherwise returns the fallback value.

func (Result[T]) OrEmpty

func (r Result[T]) OrEmpty() T

OrEmpty returns the value if the Result is Ok, otherwise returns the zero value of T.

func (Result[T]) OrF

func (r Result[T]) OrF(fallbackFn func(error) T) T

OrF returns the value if the Result is Ok, otherwise calls the fallback function with the error and returns its result.

func (Result[T]) Tap

func (r Result[T]) Tap(fn func(T)) Result[T]

Tap executes a function with the value if the Result is Ok, returning the original Result.

func (Result[T]) TapErr

func (r Result[T]) TapErr(fn func(error)) Result[T]

TapErr executes a function with the error if the Result is Err, returning the original Result.

func (Result[T]) ToAny

func (r Result[T]) ToAny() Result[any]

ToAny maybe helpful when need to convert Result[T] to Result[any].

func (Result[T]) ToOption

func (r Result[T]) ToOption() Option[T]

ToOption converts the Result to an Option, returning None if there is an error.

func (Result[T]) ToPointer

func (r Result[T]) ToPointer() *T

ToPointer converts the Result to a pointer, returning nil if there is an error.

func (Result[T]) Yield

func (r Result[T]) Yield() T

Yield yields the value from a Result, bail out if there is an error. If under `Do` notation, error will be caught.

type Suspendable

type Suspendable[T, A any] = func(context.Context, A) Result[T]

type Suspendable0

type Suspendable0[T any] = func(context.Context) Result[T]

type Suspendable2

type Suspendable2[T, A1, A2 any] = func(context.Context, A1, A2) Result[T]

type Suspendable3

type Suspendable3[T, A1, A2, A3 any] = func(context.Context, A1, A2, A3) Result[T]

type Suspendable4

type Suspendable4[T, A1, A2, A3, A4 any] = func(context.Context, A1, A2, A3, A4) Result[T]

type Suspendable5

type Suspendable5[T, A1, A2, A3, A4, A5 any] = func(context.Context, A1, A2, A3, A4, A5) Result[T]

type Suspendable6

type Suspendable6[T, A1, A2, A3, A4, A5, A6 any] = func(context.Context, A1, A2, A3, A4, A5, A6) Result[T]

type Suspendable7

type Suspendable7[T, A1, A2, A3, A4, A5, A6, A7 any] = func(context.Context, A1, A2, A3, A4, A5, A6, A7) Result[T]

type Suspendable8

type Suspendable8[T, A1, A2, A3, A4, A5, A6, A7, A8 any] = func(context.Context, A1, A2, A3, A4, A5, A6, A7, A8) Result[T]

type Suspendable9

type Suspendable9[T, A1, A2, A3, A4, A5, A6, A7, A8, A9 any] = func(context.Context, A1, A2, A3, A4, A5, A6, A7, A8, A9) Result[T]

type Suspense

type Suspense[T, A any] = func(A) Thunk[T]

func Suspend

func Suspend[T, A any](fn Suspendable[T, A]) Suspense[T, A]

type Suspense0

type Suspense0[T any] = func() Thunk[T]

SuspenseN is a type alias to represent suspended `Thunk` with N-arity arguments. A `SuspenseN` yields a `Thunk` with the same parameters as the original function which can be executed by `opera.Async`.

Example:

ctx := context.Background()

normalOp := func(a int, b string) opera.Result[string] {
    return opera.Ok(fmt.Sprintf("%d - %s", a, b))
}

suspendedOp := opera.Suspend2(normalOp) thunk := suspendedOp(10, "hello") ch := opera.Async(ctx, thunk) result := opera.Await(ch).Yield()

func Suspend0

func Suspend0[T any](fn Suspendable0[T]) Suspense0[T]

SuspendN creates a new function which delays the execution of Result-returning function represented by `SuspenseN`. A `SuspenseN` yields a `Thunk` with the same parameters as the original function which can be executed by `opera.Async`.

Example:

ctx := context.Background()

normalOp := func(a int, b string) opera.Result[string] {
    return opera.Ok(fmt.Sprintf("%d - %s", a, b))
}

suspendedOp := opera.Suspend2(normalOp) thunk := suspendedOp(10, "hello") ch := opera.Async(ctx, thunk) result := opera.Await(ch).Yield()

type Suspense2

type Suspense2[T, A1, A2 any] = func(A1, A2) Thunk[T]

func Suspend2

func Suspend2[T, A1, A2 any](fn Suspendable2[T, A1, A2]) Suspense2[T, A1, A2]

type Suspense3

type Suspense3[T, A1, A2, A3 any] = func(A1, A2, A3) Thunk[T]

func Suspend3

func Suspend3[T, A1, A2, A3 any](fn Suspendable3[T, A1, A2, A3]) Suspense3[T, A1, A2, A3]

type Suspense4

type Suspense4[T, A1, A2, A3, A4 any] = func(A1, A2, A3, A4) Thunk[T]

func Suspend4

func Suspend4[T, A1, A2, A3, A4 any](
	fn Suspendable4[T, A1, A2, A3, A4],
) Suspense4[T, A1, A2, A3, A4]

type Suspense5

type Suspense5[T, A1, A2, A3, A4, A5 any] = func(A1, A2, A3, A4, A5) Thunk[T]

func Suspend5

func Suspend5[T, A1, A2, A3, A4, A5 any](
	fn Suspendable5[T, A1, A2, A3, A4, A5],
) Suspense5[T, A1, A2, A3, A4, A5]

type Suspense6

type Suspense6[T, A1, A2, A3, A4, A5, A6 any] = func(A1, A2, A3, A4, A5, A6) Thunk[T]

func Suspend6

func Suspend6[T, A1, A2, A3, A4, A5, A6 any](
	fn Suspendable6[T, A1, A2, A3, A4, A5, A6],
) Suspense6[T, A1, A2, A3, A4, A5, A6]

type Suspense7

type Suspense7[T, A1, A2, A3, A4, A5, A6, A7 any] = func(A1, A2, A3, A4, A5, A6, A7) Thunk[T]

func Suspend7

func Suspend7[T, A1, A2, A3, A4, A5, A6, A7 any](
	fn Suspendable7[T, A1, A2, A3, A4, A5, A6, A7],
) Suspense7[T, A1, A2, A3, A4, A5, A6, A7]

type Suspense8

type Suspense8[T, A1, A2, A3, A4, A5, A6, A7, A8 any] = func(A1, A2, A3, A4, A5, A6, A7, A8) Thunk[T]

func Suspend8

func Suspend8[T, A1, A2, A3, A4, A5, A6, A7, A8 any](
	fn Suspendable8[T, A1, A2, A3, A4, A5, A6, A7, A8],
) Suspense8[T, A1, A2, A3, A4, A5, A6, A7, A8]

type Suspense9

type Suspense9[T, A1, A2, A3, A4, A5, A6, A7, A8, A9 any] = func(A1, A2, A3, A4, A5, A6, A7, A8, A9) Thunk[T]

func Suspend9

func Suspend9[T, A1, A2, A3, A4, A5, A6, A7, A8, A9 any](
	fn Suspendable9[T, A1, A2, A3, A4, A5, A6, A7, A8, A9],
) Suspense9[T, A1, A2, A3, A4, A5, A6, A7, A8, A9]

type Thunk

type Thunk[T any] = func(context.Context) Result[T]

Thunk is just a type alias for any function that defers computation until invoked with a context. A `Thunk` can yield `Result` with the help of `opera.Async`.

Example:

thunk := func(ctx context.Context) opera.Result[int] {
	// perform some computation
	return opera.Ok(42)
}
result := opera.Async(thunk).Yield()

type Tuple

type Tuple[T0, T1 any] = struct {
	V0 T0
	V1 T1
}

func Tup

func Tup[T0, T1 any](v0 T0, v1 T1) Tuple[T0, T1]

Tup creates a tuple of with 2 elements.

type Tuple3

type Tuple3[T0, T1, T2 any] = struct {
	V0 T0
	V1 T1
	V2 T2
}

func Tup3

func Tup3[T0, T1, T2 any](v0 T0, v1 T1, v2 T2) Tuple3[T0, T1, T2]

Tup3 creates a tuple of with 3 elements.

type Tuple4

type Tuple4[T0, T1, T2, T3 any] = struct {
	V0 T0
	V1 T1
	V2 T2
	V3 T3
}

func Tup4

func Tup4[T0, T1, T2, T3 any](v0 T0, v1 T1, v2 T2, v3 T3) Tuple4[T0, T1, T2, T3]

Tup4 creates a tuple of with 4 elements.

type Tuple5

type Tuple5[T0, T1, T2, T3, T4 any] = struct {
	V0 T0
	V1 T1
	V2 T2
	V3 T3
	V4 T4
}

func Tup5

func Tup5[T0, T1, T2, T3, T4 any](
	v0 T0,
	v1 T1,
	v2 T2,
	v3 T3,
	v4 T4,
) Tuple5[T0, T1, T2, T3, T4]

Tup5 creates a tuple of with 5 elements.

type Tuple6

type Tuple6[T0, T1, T2, T3, T4, T5 any] = struct {
	V0 T0
	V1 T1
	V2 T2
	V3 T3
	V4 T4
	V5 T5
}

func Tup6

func Tup6[T0, T1, T2, T3, T4, T5 any](
	v0 T0,
	v1 T1,
	v2 T2,
	v3 T3,
	v4 T4,
	v5 T5,
) Tuple6[T0, T1, T2, T3, T4, T5]

Tup6 creates a tuple of with 6 elements.

type Tuple7

type Tuple7[T0, T1, T2, T3, T4, T5, T6 any] = struct {
	V0 T0
	V1 T1
	V2 T2
	V3 T3
	V4 T4
	V5 T5
	V6 T6
}

func Tup7

func Tup7[T0, T1, T2, T3, T4, T5, T6 any](
	v0 T0,
	v1 T1,
	v2 T2,
	v3 T3,
	v4 T4,
	v5 T5,
	v6 T6,
) Tuple7[T0, T1, T2, T3, T4, T5, T6]

Tup7 creates a tuple of with 7 elements.

type Tuple8

type Tuple8[T0, T1, T2, T3, T4, T5, T6, T7 any] = struct {
	V0 T0
	V1 T1
	V2 T2
	V3 T3
	V4 T4
	V5 T5
	V6 T6
	V7 T7
}

func Tup8

func Tup8[T0, T1, T2, T3, T4, T5, T6, T7 any](
	v0 T0,
	v1 T1,
	v2 T2,
	v3 T3,
	v4 T4,
	v5 T5,
	v6 T6,
	v7 T7,
) Tuple8[T0, T1, T2, T3, T4, T5, T6, T7]

Tup8 creates a tuple of with 8 elements.

type Tuple9

type Tuple9[T0, T1, T2, T3, T4, T5, T6, T7, T8 any] = struct {
	V0 T0
	V1 T1
	V2 T2
	V3 T3
	V4 T4
	V5 T5
	V6 T6
	V7 T7
	V8 T8
}

func Tup9

func Tup9[T0, T1, T2, T3, T4, T5, T6, T7, T8 any](
	v0 T0,
	v1 T1,
	v2 T2,
	v3 T3,
	v4 T4,
	v5 T5,
	v6 T6,
	v7 T7,
	v8 T8,
) Tuple9[T0, T1, T2, T3, T4, T5, T6, T7, T8]

Tup9 creates a tuple of with 9 elements.

type Unit

type Unit interface {
	IsZero() bool
	IsUnit() bool
	// contains filtered or unexported methods
}
var U Unit = unit{/* contains filtered or unexported fields */}

Jump to

Keyboard shortcuts

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