Home

Awesome

merry Build GoDoc Go Report Card

Add context to errors, including automatic stack capture, cause chains, HTTP status code, user messages, and arbitrary values.

The package is largely based on http://github.com/go-errors/errors, with additional inspiration from https://github.com/go-errgo/errgo and https://github.com/amattn/deeperror.

V2

github.com/ansel1/merry/v2 now replaces v1. v1 will continue to be supported. v1 has been re-implemented in terms of v2, and the two packages can be used together and interchangeably.

There are some small enhancements and changes to v1 with the introduction of v2:

Installation

go get github.com/ansel1/merry

Features

Merry errors work a lot like google's golang.org/x/net/context package. Merry errors wrap normal errors with a context of key/value pairs. Like contexts, merry errors are immutable: adding a key/value to an error always creates a new error which wraps the original.

merry comes with built-in support for adding information to errors:

You can also add your own additional information.

The stack capturing feature can be turned off for better performance, though it's pretty fast. Benchmarks on an 2017 MacBook Pro, with go 1.10:

BenchmarkNew_withStackCapture-8      	 2000000	       749 ns/op
BenchmarkNew_withoutStackCapture-8   	20000000	        64.1 ns/op

Details

Basic Usage

The package contains functions for creating new errors with stacks, or adding a stack to error instances. Functions with add context (e.g. WithValue()) work on any error, and will automatically convert them to merry errors (with a stack) if necessary.

Capturing the stack can be globally disabled with SetStackCaptureEnabled(false)

Functions which get context values from errors also accept error, and will return default values if the error is not merry, or doesn't have that key attached.

All the functions which create or attach context return concrete instances of *Error. *Error implements methods to add context to the error (they mirror the functions and do the same thing). They allow for a chainable syntax for adding context.

Example:

package main

import (
    "github.com/ansel1/merry"
    "errors"
)

var InvalidInputs = errors.New("Input is invalid")

func main() {
    // create a new error, with a stacktrace attached
    err := merry.New("bad stuff happened")
    
    // create a new error with format string, like fmt.Errorf
    err = merry.Errorf("bad input: %v", os.Args)
    
    // capture a fresh stacktrace from this callsite
    err = merry.Here(InvalidInputs)
    
    // Make err merry if it wasn't already.  The stacktrace will be captured here if the
    // error didn't already have one.  Also useful to cast to *Error 
    err = merry.Wrap(err, 0)

    // override the original error's message
    err.WithMessagef("Input is invalid: %v", os.Args)
    
    // Use Is to compare errors against values, which is a common golang idiom
    merry.Is(err, InvalidInputs) // will be true
    
    // associated an http code
    err.WithHTTPCode(400)
    
    perr := parser.Parse("blah")
    err = Wrap(perr, 0)
    // Get the original error back
    merry.Unwrap(err) == perr  // will be true
    
    // Print the error to a string, with the stacktrace, if it has one
    s := merry.Details(err)
    
    // Just print the stacktrace (empty string if err is not a RichError)
    s := merry.Stacktrace(err)

    // Get the location of the error (the first line in the stacktrace)
    file, line := merry.Location(err)
    
    // Get an HTTP status code for an error.  Defaults to 500 for non-nil errors, and 200 if err is nil.
    code := merry.HTTPCode(err)
    
}

See inline docs for more details.

Plugs

License

This package is licensed under the MIT license, see LICENSE.MIT for details.