errors

package
v0.1.0-alpha.0...-0b1224c Latest Latest
Warning

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

Go to latest
Published: Apr 5, 2019 License: Apache-2.0 Imports: 5 Imported by: 0

Documentation

Overview

Package errors implements a basic error wrapping pattern, so that errors can be annotated with additional information without losing the original error.

Example:

import "github.com/interstellar/starlight/errors"

func query() error {
	err := pq.Exec("SELECT...")
	if err != nil {
		return errors.Wrap(err, "select query failed")
	}

	err = pq.Exec("INSERT...")
	if err != nil {
		return errors.Wrap(err, "insert query failed")
	}

	return nil
}

func main() {
	err := query()
	if _, ok := errors.Root(err).(sql.ErrNoRows); ok {
		log.Println("There were no results")
		return
	} else if err != nil {
		log.Println(err)
		return
	}

	log.Println("success")
}

When to wrap errors

Errors should be wrapped with additional messages when the context is ambiguous. This includes when the error could arise in multiple locations in the same function, when the error is very common and likely to appear at different points in the call tree (e.g., JSON serialization errors), or when you need specific parameters alongside the original error message.

Error handling best practices

Errors are part of a function's interface. If you expect the caller to perform conditional error handling, you should document the errors returned by your function in a function comment, and include it as part of your unit tests.

Be disciplined about validating user input. Programs should draw a very clear distinction between user errors and internal errors.

Avoid redundant error logging. If you return an error, assume it will be logged higher up the call stack. For a given project, choose an appropriate layer to handle error logging.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Data

func Data(err error) map[string]interface{}

Data returns the data item in err, if any.

func Detail

func Detail(err error) string

Detail returns the detail message contained in err, if any. An error has a detail message if it was made by WithDetail or WithDetailf.

func New

func New(text string) error

New returns an error that formats as the given text.

func Root

func Root(e error) error

Root returns the original error that was wrapped by one or more calls to Wrap. If e does not wrap other errors, it will be returned as-is.

func Stack

func Stack(err error) *runtime.Frames

Stack returns the stack trace of an error. If the error has no stack information, it returns an empty stack trace.

func Sub

func Sub(root, err error) error

Sub returns an error containing root as its root and taking all other metadata (stack trace, detail, message, and data items) from err.

Sub returns nil when either root or err is nil.

Use this when you need to substitute a new root error in place of an existing error that may already hold a stack trace or other metadata.

Example
package main

import (
	"github.com/interstellar/starlight/errors"
)

var ErrInvalidKey = errors.New("invalid key")

func main() {
	err := sign()
	if err != nil {
		err = errors.Sub(ErrInvalidKey, err)
		return
	}
}

func sign() error { return nil }
Output:

Example (Return)
package main

import (
	"github.com/interstellar/starlight/errors"
)

var ErrInvalidKey = errors.New("invalid key")

func main() {
	err := sign()
	err = errors.Sub(ErrInvalidKey, err)
	return
}

func sign() error { return nil }
Output:

func WithData

func WithData(err error, keyval ...interface{}) error

WithData returns a new error that wraps err as a chain error message containing a value of type map[string]interface{} as an extra data item. The map contains the values in the map in err, if any, plus the items in keyval. Keyval takes the form

k1, v1, k2, v2, ...

Values kN must be strings. Calling Data on the returned error yields the map. Note that if err already has a data item of any other type, it will not be accessible via the returned error value.

func WithDetail

func WithDetail(err error, text string) error

WithDetail returns a new error that wraps err as a chain error messsage containing text as its additional context. Function Detail will return the given text when called on the new error value.

func WithDetailf

func WithDetailf(err error, format string, v ...interface{}) error

WithDetailf is like WithDetail, except it formats the detail message as in fmt.Printf. Function Detail will return the formatted text when called on the new error value.

func Wrap

func Wrap(err error, a ...interface{}) error

Wrap adds a context message and stack trace to err and returns a new error with the new context. Arguments are handled as in fmt.Print. Use Root to recover the original error wrapped by one or more calls to Wrap. Use Stack to recover the stack trace. Wrap returns nil if err is nil.

func Wrapf

func Wrapf(err error, format string, a ...interface{}) error

Wrapf is like Wrap, but arguments are handled as in fmt.Printf.

Types

type Writer

type Writer struct {
	// contains filtered or unexported fields
}

Writer is in an implementation of the "sticky error writer" pattern as described in https://blog.golang.org/errors-are-values.

A Writer makes one call on the underlying writer for each call to Write, until an error is returned. From that point on, it makes no calls on the underlying writer, and returns the same error value every time.

func NewWriter

func NewWriter(w io.Writer) *Writer

NewWriter returns a new Writer that writes to w until an error is returned.

func (*Writer) Err

func (w *Writer) Err() error

Err returns the first error encountered by Write, if any.

func (*Writer) Write

func (w *Writer) Write(buf []byte) (n int, err error)

Write makes one call on the underlying writer if no error has previously occurred.

func (*Writer) Written

func (w *Writer) Written() int64

Written returns the number of bytes written to the underlying writer.

Jump to

Keyboard shortcuts

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