Skip to content

proposal: errors/errd: helper package for deferred error handlers #32676

@rsc

Description

@rsc

The try proposal (#32437) uses a placeholder fmt.HandleErrorf to annotate errors.
We do not intend that to be the actual function name. It was a blank to be filled in.
Here is one possible way to fill in that blank.

// Package errd provides error-handling functions.
// All of them are meant to be deferred,
// with the address of the function's error result
// as the first argument. For example:
//
//	defer errd.Trace(&err)
//
// All of the functions take action only when err != nil
// (meaning the function in which the defer appears is
// itself returning a non-nil error); they are no-ops when err == nil.
package errd // import "errors/errd"

// Trace prints the error and the current goroutine's stack trace.
// It does nothing when *errp == nil.
//
// Example:
//
//	defer errd.Trace(&err)
//
func Trace(errp *error)

// Apply applies the function f to the error (*errp = f(*errp)).
// It does nothing when *errp == nil.
//
// Example:
//
//	defer errd.Apply(&err, func(err error) error {
//		if err == io.EOF {
//			err = io.ErrUnexpectedEOF
//		}
//	})
//
func Apply(errp *error, f func(err error) error)

// Add adds context to the error.
// The result cannot be unwrapped to recover the original error.
// It does nothing when *errp == nil.
//
// Example:
//
//	defer errd.Add(&err, "copy %s %s", src, dst)
//
// This example is equivalent to:
//
//	defer errd.Apply(&err, func(err error) error {
//		err = fmt.Errorf("copy %s %s: %v", src, dst)
//	})
//
// See Wrap for an equivalent function that allows
// the result to be unwrapped.
func Add(errp *error, format string, args ...interface{})

// Wrap adds context to the error and allows
// unwrapping the result to recover the original error.
//
// Example:
//
//	defer errd.Wrap(&err, "copy %s %s", src, dst)
//
// This example is equivalent to:
//
//	defer errd.Apply(&err, func(err error) error {
//		err = fmt.Errorf("copy %s %s: %w", src, dst)
//	})
//
// See Add for an equivalent function that does not allow
// the result to be unwrapped.
func Wrap(errp *error, format string, args ...interface{})

Thoughts and improvements welcome.

/cc @mpvl @jba @neild

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions