go: github.com/samsarahq/go/oops Index | Files | Directories

package oops

import "github.com/samsarahq/go/oops"

Package oops adds detailed stacktraces to your Go errors.

To use the oops package, calls oops.Errorf when creating a new error, and oops.Wrapf when returning nested errors. To access the original error, use oops.Cause. Each function in the callstack can add extra debugging information to help you track down errors.

An example error (from the program below) looks as follows:

20 is too large!

main.Foo
  github.com/samsarahq/go/oops/example/main.go:12
main.Legacy
  github.com/samsarahq/go/oops/example/main.go:19
main.Bar: Legacy(20) didn't work
  github.com/samsarahq/go/oops/example/main.go:24
main.Go.func1
  github.com/samsarahq/go/oops/example/main.go:35

main.Go: goroutine had a problem
  github.com/samsarahq/go/oops/example/main.go:38
main.main
  github.com/samsarahq/go/oops/example/main.go:42
runtime.main
  runtime/proc.go:185

The first time oops.Errorf or oops.Wrapf is called, it captures a stacktrace. To keep your stacktraces as detailed as possible, it is best to call oops.Wrapf every time you return an error. If you have no context to add, you can always pass an empty format string to oops.Wrapf.

When adding oops to an existing package or program, you might have intermediate functions that don't yet call oops.Wrapf when returning errors. That is no problem, as later calls to oops.Wrapf will attach their messages to right stackframe. However, you might as well add oops.Wrapf there as well!

Usage:

package main

import (
  "fmt"

  "github.com/samsarahq/go/oops"
)

// Foo creates new errors using oops.Errorf.
func Foo(i int) error {
  if i > 10 {
    return oops.Errorf("%d is too large!", i)
  }
  return nil
}

// Legacy is old code that does not use oops.
func Legacy(i int) error {
  return Foo(i)
}

// Bar wraps errors using Wrapf.
func Bar() error {
  if err := Legacy(20); err != nil {
    return oops.Wrapf(err, "Legacy(20) didn't work")
  }
  return nil
}

// Go wraps errors using Wrapf after receiving one from a channel!
func Go() error {
  ch := make(chan error)

  go func() {
    ch <- Bar()
  }()

  return oops.Wrapf(<-ch, "goroutine had a problem")
}

func main() {
  if err := Go(); err != nil {
    fmt.Print(err)
  }
}

Index

Package Files

doc.go oops.go types.go xerrors.go

func As Uses

func As(err error, target interface{}) bool

As finds the first error in err's chain that matches the type to which target points, and if so, sets the target to its value and returns true. An error matches a type if it is assignable to the target type, or if it has a method As(interface{}) bool such that As(target) returns true. As will panic if target is not a non-nil pointer to a type which implements error or is of interface type.

The As method should set the target to its value and return true if err matches the type to which target points.

func Cause Uses

func Cause(err error) error

Cause extracts the cause error of an oops error. If err is not an oops error, err itself is returned.

You can use Cause to check if an error is an expected error. For example, if you know than EOF error is fine, you can handle it with Cause.

func Errorf Uses

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

Errorf creates a new error with a reason and a stacktrace.

Use Errorf in places where you would otherwise return an error using fmt.Errorf or errors.New.

Note that the result of Errorf includes a stacktrace. This means that Errorf is not suitable for storing in global variables. For such errors, keep using errors.New.

func Frames Uses

func Frames(err error) [][]Frame

Frames extracts all frames from an oops error. If err is not an oops error, nil is returned.

func Is Uses

func Is(err, target error) bool

Is reports whether any error in err's chain matches target.

An error is considered to match a target if it is equal to that target or if it implements a method Is(error) bool such that Is(target) returns true.

func Recover Uses

func Recover(p interface{}) error

Recover recovers from a panic in a defer. If there is no panic, Recover() returns nil. To use, call oops.Recover(recover()) and compare the result to nil.

func Unwrap Uses

func Unwrap(err error) error

Unwrap returns the result of calling the Unwrap method on err, if err implements Unwrap. Otherwise, Unwrap returns nil.

func Wrapf Uses

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

Wrapf annotates an error with a reason and a stacktrace. If err is nil, Wrapf returns nil.

Use Wrapf in places where you would otherwise return an error directly. If the error passed to Wrapf is nil, Wrapf will also return nil. This makes it safe to use in one-line return statements.

To check if a wrapped error is a specific error, such as io.EOF, you can extract the error passed in to Wrapf using Cause.

type Frame Uses

type Frame struct {
    File     string
    Function string
    Line     int
    Reason   string
}

A Frame represents a Frame in an oops callstack. The Reason is the manual annotation passed to oops.Wrapf.

type Wrapper Uses

type Wrapper interface {
    // Unwrap returns the next error in the error chain.
    // If there is no next error, Unwrap returns nil.
    Unwrap() error
}

A Wrapper provides context around another error.

Directories

PathSynopsis
example

Package oops imports 6 packages (graph) and is imported by 12 packages. Updated 2019-05-24. Refresh now. Tools for package owners.