errorkit

package
v0.296.0 Latest Latest
Warning

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

Go to latest
Published: Apr 9, 2025 License: Apache-2.0 Imports: 7 Imported by: 4

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func As added in v0.201.0

func As[T error](err error) (T, bool)

As function serves as a shorthand to enable one-liner error handling with errors.As. It's meant to be used within an if statement, much like Lookup functions such as os.LookupEnv.

Example
package main

import (
	"fmt"

	"go.llib.dev/frameless/pkg/errorkit"
)

type MyError struct {
	Msg string
}

func (err MyError) Error() string {
	return err.Msg
}

func main() {
	var err error // some error to be checked

	if err, ok := errorkit.As[MyError](err); ok {
		fmt.Println(err.Msg)
	}
}
Output:

func F added in v0.289.0

func F(format string, a ...any) error

F functions similarly to fmt.Errorf but includes tracing capabilities. In the future, it may incorporate additional utilities from errorkit.

Example
package main

import (
	"fmt"

	"go.llib.dev/frameless/pkg/errorkit"
)

func main() {
	const ErrBoom errorkit.Error = "boom!"

	err := errorkit.F("something went wrong: %w", ErrBoom)

	if traced, ok := errorkit.As[errorkit.TracedError](err); ok {
		fmt.Println(traced.Error())
	}

	fmt.Println(err.Error())
}
Output:

func Finish

func Finish(returnErr *error, blk func() error)

Finish is a helper function that can be used from a deferred context.

Usage:

defer errorkit.Finish(&returnError, rows.Close)
Example (SqlRows)
package main

import (
	"database/sql"

	"go.llib.dev/frameless/pkg/errorkit"
)

func main() {
	var db *sql.DB

	myExampleFunction := func() (rErr error) {
		rows, err := db.Query("SELECT FROM mytable")
		if err != nil {
			return err
		}
		defer errorkit.Finish(&rErr, rows.Close)

		for rows.Next() {
			if err := rows.Scan(); err != nil {
				return err
			}
		}
		return rows.Err()
	}

	if err := myExampleFunction(); err != nil {
		panic(err.Error())
	}
}
Output:

func FinishOnError added in v0.260.0

func FinishOnError(returnErr *error, blk func())

FinishOnError is a helper function that can be used from a deferred context. It runs the block conditionally, when the return error, which was assigned by the `return` keyword is not nil.

Usage:

defer errorkit.FinishOnError(&returnError, func() { rollback(ctx) })
Example
package main

import (
	"go.llib.dev/frameless/pkg/errorkit"
)

func main() {
	// example function
	var _ = func() (rerr error) {
		defer errorkit.FinishOnError(&rerr, func() { /* do something when the */ })

		return errorkit.Error("boom")
	}
}
Output:

func LookupContext

func LookupContext(err error) (context.Context, bool)

func Merge

func Merge(errs ...error) error

Merge will combine all given non nil error values into a single error value. If no valid error is given, nil is returned. If only a single non nil error value is given, the error value is returned.

Example
package main

import (
	"fmt"

	"go.llib.dev/frameless/pkg/errorkit"
)

func main() {
	// creates an error value that combines the input errors.
	err := errorkit.Merge(fmt.Errorf("foo"), fmt.Errorf("bar"), nil)
	_ = err
}
Output:

func MergeErrFunc added in v0.285.0

func MergeErrFunc(errFuncs ...ErrFunc) func() error

func NullErrFunc added in v0.285.0

func NullErrFunc() error

func Recover added in v0.184.0

func Recover(returnErr *error)

Recover will attempt a recover, and if recovery yields a value, it sets it as an error.

func RecoverWith added in v0.272.0

func RecoverWith(blk func(r any))

RecoverWith will attempt a recover, and if recovery yields a non nil value, it executs the passed function.

Example
package main

import (
	"go.llib.dev/frameless/pkg/errorkit"
)

func main() {
	defer errorkit.RecoverWith(func(r any) { /* do something with "r" */ })

	/* do something that might panic */
}
Output:

func WithContext added in v0.281.0

func WithContext(err error, ctx context.Context) error

WithContext will combine an error with a context, so the current context can be used at the place of error handling. This can be useful if tracing ID and other helpful values such as additional logging fields are kept in the context.

Example
package main

import (
	"context"
	"fmt"

	"go.llib.dev/frameless/pkg/errorkit"
)

func main() {
	err := fmt.Errorf("foo bar baz")
	ctx := context.Background()

	err = errorkit.WithContext(err, ctx)
	_, _ = errorkit.LookupContext(err) // ctx, true
}
Output:

func WithTrace added in v0.280.0

func WithTrace(err error) error
Example
package main

import (
	"errors"
	"fmt"

	"go.llib.dev/frameless/pkg/errorkit"
)

func main() {
	const ErrBase errorkit.Error = "some error that we get back from a function call"

	// traced error that we can return
	err := errorkit.WithTrace(ErrBase)
	// if we receive back a traced error from a function call, calling WithTrace wonn't reset the trace
	err = errorkit.WithTrace(err)
	// maybe we have some additional trace wrapping
	err = fmt.Errorf("wrapping the erro: %w", err)

	var traced errorkit.TracedError
	_ = errors.As(err, &traced) // true
	_ = traced.Stack            // stack trace
}
Output:

Types

type ErrFunc added in v0.285.0

type ErrFunc = func() error

ErrFunc is a function that checks whether a stateful system currently has an error. For example context.Context#Err is an ErrFunc.

type Error

type Error string

Error is an implementation for the error interface that allow you to declare exported globals with the `consttypes` keyword.

TL;DR:
  consttypes ErrSomething errorkit.Error = "something is an error"
Example
package main

import (
	"errors"

	"go.llib.dev/frameless/pkg/errorkit"
)

func main() {
	var (
		err1 error = errors.New("first error")
		err2 error = errors.New("second error")
		err3 error = nil
	)

	err := errorkit.Merge(err1, err2, err3)
	errors.Is(err, err1) // true
	errors.Is(err, err2) // true
	errors.Is(err, err3) // true
}
Output:

func (Error) Error

func (err Error) Error() string

Error implement the error interface

Example
package main

import (
	"go.llib.dev/frameless/pkg/errorkit"
)

func main() {
	const ErrSomething errorkit.Error = "something is an error"

	_ = ErrSomething
}
Output:

func (Error) F added in v0.271.0

func (err Error) F(format string, a ...any) error

F will format the error value

func (Error) Wrap added in v0.271.0

func (err Error) Wrap(oth error) error

Wrap will bundle together another error value with this Error, and return an error value that contains both of them.

type ErrorHandler

type ErrorHandler interface {
	// HandleError allow the interactor implementation to be notified about unexpected situations.
	HandleError(ctx context.Context, err error) error
}

ErrorHandler describes that an object able to handle error use-cases for its purpose.

For e.g. if the component is a pubsub subscription event handler, then implementing ErrorHandler means it suppose to handle unexpected use-cases such as connection interruption.

type TracedError added in v0.289.0

type TracedError struct {
	Err   error
	Stack []runtime.Frame
}

func (TracedError) As added in v0.289.0

func (err TracedError) As(target any) bool

func (TracedError) Error added in v0.289.0

func (err TracedError) Error() string

func (TracedError) Is added in v0.289.0

func (err TracedError) Is(target error) bool

func (TracedError) Unwrap added in v0.289.0

func (err TracedError) Unwrap() error

type UserError

type UserError struct {
	// Code is a constant string value that expresses the user's error scenario.
	// The caller who receives the error will use this code to present the UserError to their users and,
	// most likely, provide a localised error message about the error scenario to the end user.
	// Traditionally this should be a string without any white space.
	//
	// Example: "foo-is-forbidden-with-active-baz"
	Code constant.String `ext:"id"`
	// Message is the error message meant to be read by a developer working on the implementation of the caller.
	// It is not expected to be seen by end users.
	// It might be written in English for portability reasons.
	//
	// Example: "Authentication failed due to incorrect username or password."
	Message constant.String
}
Example
package main

import (
	"errors"
	"fmt"
	"math/rand"

	"go.llib.dev/frameless/pkg/errorkit"
)

func main() {
	fooEntityID := rand.Int()
	bazEntityID := rand.Int()

	usrerr := errorkit.UserError{
		Code:    "foo-is-forbidden-with-active-baz",
		Message: "It is forbidden to execute Foo when you have an active Baz",
	}

	var err error = usrerr.F("Foo(ID:%d) /Baz(ID:%d)", fooEntityID, bazEntityID)

	// add some details using error wrapping
	err = fmt.Errorf("some wrapper layer: %w", err)

	// retrieve with errorkit.As
	if ue, ok := errorkit.As[errorkit.UserError](err); ok {
		fmt.Printf("%#v\n", ue)
	}
	// retrieve with errors pkg
	if ue := (errorkit.UserError{}); errors.As(err, &ue) {
		fmt.Printf("%#v\n", ue)
	}
	if errors.Is(err, errorkit.UserError{}) {
		fmt.Println("it's a Layer 8 error")
	}

	// retrieve with errorkit pkg
	if userError, ok := errorkit.LookupUserError(err); ok {
		fmt.Printf("%#v\n", userError)
	}
}
Output:

func LookupUserError

func LookupUserError(err error) (UserError, bool)
Example
package main

import (
	"fmt"

	"go.llib.dev/frameless/pkg/errorkit"
)

func main() {
	err := errorkit.UserError{
		Code:    "constant-err-scenario-code",
		Message: "some message for the dev",
	}
	if userError, ok := errorkit.LookupUserError(err); ok {
		fmt.Printf("%#v\n", userError)
	}
}
Output:

func (UserError) Error

func (err UserError) Error() string

func (UserError) F added in v0.281.0

func (err UserError) F(format string, a ...any) error

F will format the error value

func (UserError) Wrap added in v0.278.0

func (err UserError) Wrap(oth error) error

Jump to

Keyboard shortcuts

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