Giter VIP home page Giter VIP logo

errs's Introduction

errs

GoDoc Sourcegraph Go Report Card

errs is a package for making errors friendly and easy.

Creating Errors

The easiest way to use it, is to use the package level New function. It's much like fmt.Errorf, but better. For example:

func checkThing() error {
	return errs.New("what's up with %q?", "zeebo")
}

Why is it better? Errors come with a stack trace that is only printed when a "+" character is used in the format string. This should retain the benefits of being able to diagnose where and why errors happen, without all of the noise of printing a stack trace in every situation. For example:

func doSomeRealWork() {
	err := checkThing()
	if err != nil {
		fmt.Printf("%+v\n", err) // contains stack trace if it's a errs error.
		fmt.Printf("%v\n", err)  // does not contain a stack trace
		return
	}
}

Error Classes

You can create a Class of errors and check if any error was created by that class. The class name is prefixed to all of the errors it creates. For example:

var Unauthorized = errs.Class("unauthorized")

func checkUser(username, password string) error {
	if username != "zeebo" {
		return Unauthorized.New("who is %q?", username)
	}
	if password != "hunter2" {
		return Unauthorized.New("that's not a good password, jerkmo!")
	}
	return nil
}

func handleRequest() {
	if err := checkUser("zeebo", "hunter3"); Unauthorized.Has(err) {
		fmt.Println(err)
	}

	// output:
	// unauthorized: that's not a good password, jerkmo!
}

Classes can also Wrap other errors, and errors may be wrapped multiple times. For example:

var (
	Error        = errs.Class("mypackage")
	Unauthorized = errs.Class("unauthorized")
)

func deep3() error {
	return fmt.Errorf("ouch")
}

func deep2() error {
	return Unauthorized.Wrap(deep3())
}

func deep1() error {
	return Error.Wrap(deep2())
}

func deep() {
	fmt.Println(deep1())

	// output:
	// mypackage: unauthorized: ouch
}

In the above example, both Error.Has(deep1()) and Unauthorized.Has(deep1()) would return true, and the stack trace would only be recorded once at the deep2 call.

In addition, when an error has been wrapped, wrapping it again with the same class will not do anything. For example:

func doubleWrap() {
	fmt.Println(Error.Wrap(Error.New("foo")))

	// output:
	// mypackage: foo
}

This is to make it an easier decision if you should wrap or not (you should).

Utilities

Classes is a helper function to get a slice of classes that an error has. The latest wrap is first in the slice. For example:

func getClasses() {
	classes := errs.Classes(deep1())
	fmt.Println(classes[0] == &Error)
	fmt.Println(classes[1] == &Unauthorized)

	// output:
	// true
	// true
}

Finally, a helper function, Unwrap is provided to get the wrapped error in cases where you might want to inspect details. For example:

var Error = errs.Class("mypackage")

func getHandle() (*os.File, error) {
	fh, err := os.Open("neat_things")
	if err != nil {
		return nil, Error.Wrap(err)
	}
	return fh, nil
}

func checkForNeatThings() {
	fh, err := getHandle()
	if os.IsNotExist(errs.Unwrap(err)) {
		panic("no neat things?!")
	}
	if err != nil {
		panic("phew, at least there are neat things, even if i can't see them")
	}
	fh.Close()
}

It knows about both the Unwrap() error and Unwrap() []error methods that are often used in the community, and will call them as many times as possible.

Defer

The package also provides WrapP versions of Wrap that are useful in defer contexts. For example:

func checkDefer() (err error) {
	defer Error.WrapP(&err)

	fh, err := os.Open("secret_stash")
	if err != nil {
		return nil, err
	}
	return fh.Close()
}

Groups

Groups allow one to collect a set of errors. For example:

func tonsOfErrors() error {
	var group errs.Group
	for _, work := range someWork {
		group.Add(maybeErrors(work))
	}
	return group.Err()
}

Some things to note:

  • The Add method only adds to the group if the passed in error is non-nil.
  • The Err method returns an error only if non-nil errors have been added, and additionally returns just the error if only one error was added. Thus, we always have that if you only call group.Add(err), then group.Err() == err.

The returned error will format itself similarly:

func groupFormat() {
	var group errs.Group
	group.Add(errs.New("first"))
	group.Add(errs.New("second"))
	err := group.Err()

	fmt.Printf("%v\n", err)
	fmt.Println()
	fmt.Printf("%+v\n", err)

	// output:
	// first; second
	//
	// group:
	// --- first
	//     ... stack trace
	// --- second
	//     ... stack trace
}

Contributing

errs is released under an MIT License. If you want to contribute, be sure to add yourself to the list in AUTHORS.

errs's People

Contributors

zeebo avatar kaloyan-raev avatar egonelbre avatar ifraixedes avatar jtolio avatar thepaul avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.