errutil

package
v1.148.2 Latest Latest
Warning

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

Go to latest
Published: Jul 11, 2026 License: MIT Imports: 3 Imported by: 0

Documentation

Overview

Package errutil provides small, reusable helpers for consistent error handling in Go applications.

Many Go services repeat the same error-handling patterns: appending cleanup errors, enriching failures with call-site context, and preserving compatibility with the standard errors API. This package centralizes those patterns so teams can keep error paths concise and predictable.

Top features:

  • Trace annotates an error with runtime caller metadata (file, line, function) while preserving the original error with %w wrapping. This gives developers immediate debugging context without losing errors.Is/errors.As behavior.
  • JoinFnError executes an error-producing function and joins its result into an existing error value using errors.Join. This is useful for defer/cleanup logic where secondary failures must not overwrite the primary error.
  • Errors enumerates the individual errors aggregated within an errors.Join value, returning a single-element slice for a plain error and nil for nil.
  • Nil-safe behavior: Trace(nil) returns nil, and JoinFnError naturally supports nil and non-nil combinations through errors.Join semantics.

Benefits:

  • reduces boilerplate in error-return and defer paths
  • improves observability and diagnosis of production failures
  • encourages idiomatic Go error composition based on errors.Join and %w

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrNilErrorFunc = errors.New("errutil: nil ErrorFunc")

ErrNilErrorFunc is joined into the target error by JoinFnError when the supplied ErrorFunc is nil, surfacing the programming mistake without panicking.

Functions

func Errors

func Errors(err error) []error

Errors returns the individual errors aggregated within err.

It lets callers enumerate the parts of an aggregate produced by errors.Join:

  • a nil err yields a nil slice;
  • an err implementing Unwrap() []error (such as the value returned by errors.Join) yields a copy of its aggregated errors;
  • any other non-nil err yields a single-element slice holding err.

The returned slice never aliases the internal storage of the aggregate error, so callers may retain and modify it freely.

func JoinFnError

func JoinFnError(err *error, fn ErrorFunc)

JoinFnError executes fn and joins its error into *err.

This helper is intended for defer/cleanup paths where secondary failures should be preserved without overwriting a primary error. It is typically used as:

func do() (err error) {
	f, err := open()
	if err != nil {
		return err
	}
	defer errutil.JoinFnError(&err, f.Close)
	// ...
}

err must point at the error that will ultimately be returned, usually the address of a named return value; passing the address of a local variable that is not returned silently discards the joined error.

If err is nil the call is a no-op. If fn is nil, ErrNilErrorFunc is joined into *err. The primary error is left untouched when fn returns nil.

Example
package main

import (
	"errors"
	"fmt"

	"github.com/tecnickcom/nurago/pkg/errutil"
)

func main() {
	err := errors.New("original error")

	fn := func() error {
		return errors.New("function error")
	}

	errutil.JoinFnError(&err, fn)

	fmt.Println(err)

}
Output:
original error
function error
Example (Defer)
package main

import (
	"errors"
	"fmt"

	"github.com/tecnickcom/nurago/pkg/errutil"
)

func main() {
	// JoinFnError is designed for defer/cleanup: err must be a named return
	// value so the deferred call can amend it after the function body runs.
	process := func() (err error) { //nolint:nonamedreturns // JoinFnError amends the return via its address
		closer := func() error {
			return errors.New("close failed")
		}
		defer errutil.JoinFnError(&err, closer)

		return errors.New("primary failure")
	}

	fmt.Println(process())

}
Output:
primary failure
close failed

func Trace

func Trace(err error) error

Trace wraps err with caller file, line, and function metadata.

It returns nil when err is nil. The original error is wrapped with %w so errors.Is and errors.As continue to work. When caller metadata cannot be recovered, the function name falls back to "unknown".

The file path is the one recorded by the compiler: it is absolute for a plain build and module-relative when the binary is built with -trimpath. Avoid relying on its exact form and prefer -trimpath for release builds to keep build-host paths out of error messages and logs.

Example
package main

import (
	"errors"
	"fmt"

	"github.com/tecnickcom/nurago/pkg/errutil"
)

func main() {
	err := errors.New("example error")
	testErr := errutil.Trace(err)

	fmt.Println(testErr)
}

Types

type ErrorFunc

type ErrorFunc func() error

ErrorFunc is a deferred cleanup/action callback that may return an error.

Jump to

Keyboard shortcuts

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