errors

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Oct 26, 2023 License: BSD-2-Clause Imports: 7 Imported by: 2

README

Error module used internally at Primal Skill, inspired by upspin/errors and pkg/errors.

Install

Get the module:

go get -u github.com/primalskill/errors

Import it in your code:

import "github.com/primalskill/errors"

Basic Usage

package main

import (
  "fmt"
  "github.com/primalskill/errors"
)

func main() {
  err1 := errors.E("this is an error", errors.WithMeta("metaKey1", "meta value 1", "isAuth", true))
  err2 := errors.E("embedded error", err1, errors.WithMeta("additionalMeta", 246))

  fmt.Println(err2.Error()) // outputs the error message: embedded error

  // Convert stdlib error to errors.Error
  var ee *errors.Error
  errors.As(err2, &ee)

  fmt.Printf("%+v", ee.Meta) // outputs err2 Meta

  m := errors.GetMeta(err2) // get the Meta with a helper func
  fmt.Printf("%+v", m) // outputs the Meta attached to err2

  uErr := errors.Unwrap(err2) // unwraps err2 to get err1
  fmt.Println(uErr.Error()) // outputs: this is an error
}

Documentation

Overview

Package errors implements custom error handling by decorating the standard Error interface with additional meta data.

Installation

To install the module, you will need Go 1.13 or a newer version.

Getting the module:

$ go get -u github.com/primalskill/errors

Import it in your code:

import "github.com/primalskill/errors"

Overview

Always use the E() function to create new errors, to which you can add additional data.

package main

import (
  "fmt"
  "github.com/primalskill/errors"
)

func main() {
  err1 := errors.E("this is an error", errors.WithMeta("metaKey1", "meta value 1", "isAuth", true))
  err2 := errors.E("embedded error", err1, errors.WithMeta("additionalMeta", 246))

  fmt.Println(err2.Error()) // outputs the error message: embedded error

  // Convert stdlib error to errors.Error
  var ee *errors.Error
  errors.As(err2, &ee)

  fmt.Printf("%+v", ee.Meta) // outputs err2 Meta

  m := errors.GetMeta(err2) // get the Meta with a helper func
  fmt.Printf("%+v", m) // outputs the Meta attached to err2

  uErr := errors.Unwrap(err2) // unwraps err2 to get err1
  fmt.Println(uErr.Error()) // outputs: this is an error
}

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func As

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

As finds the first error in err's chain that matches target, and if so, sets target to that error value and returns true. Otherwise, it returns false.

The chain consists of err itself followed by the sequence of errors obtained by repeatedly calling Unwrap.

An error matches target if the error's concrete value is assignable to the value pointed to by target, or if the error has a method As(interface{}) bool such that As(target) returns true. In the latter case, the As method is responsible for setting target.

An error type might provide an As method so it can be treated as if it were a different error type.

As panics if target is not a non-nil pointer to either a type that implements error, or to any interface type.

func E

func E(msg string, args ...interface{}) error

E return a new error and sets the required msg argument as the error message. Additional arguments like a Meta map or another error can be passed into the function that will be set on the error.

Example
package main

import (
	"fmt"
	"github.com/primalskill/errors"
)

func main() {
	err := errors.E("this is an error")
	fmt.Println(err.Error())

}
Output:
this is an error
Example (Meta)
package main

import (
	"fmt"
	"github.com/primalskill/errors"
)

func main() {

	// err will carry a Meta map.
	err := errors.E("this is an error with meta", errors.WithMeta("myKey", "value_testing"))

	var e *errors.Error
	errors.As(err, &e)

	fmt.Printf("%+v", e.Meta)

}
Output:
[myKey:value_testing]

func Is

func Is(err, target error) bool

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

The chain consists of err itself followed by the sequence of errors obtained by repeatedly calling Unwrap.

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.

An error type might provide an Is method so it can be treated as equivalent to an existing error. For example, if MyError defines

func (m MyError) Is(target error) bool { return target == fs.ErrExist }

then Is(MyError{}, fs.ErrExist) returns true. See syscall.Errno.Is for an example in the standard library.

func MergeMeta

func MergeMeta(err error, m Meta) (error, bool)

MergeMeta will merge m to err.Meta if err is of type errors.Error and returns TRUE if the operation was succesful, FALSE otherwise.

func PrettyPrint

func PrettyPrint(err error) string

PrettyPrint is a helper method to *Error.PrettyPrint. This should be used in development.

Example
package main

import (
	"fmt"
	"github.com/primalskill/errors"
)

func main() {
	err := errors.E("my error", errors.WithMeta("key", "value"))
	fmt.Printf("%s", errors.PrettyPrint(err))
}

func Unwrap

func Unwrap(err error) error

Unwrap returns the result of calling the Unwrap method on err, if err's type contains an Unwrap method returning error. Otherwise, Unwrap returns nil.

Example
package main

import (
	"fmt"
	"github.com/primalskill/errors"
)

func main() {
	err1 := errors.E("error 1")
	err2 := errors.E("error 2", err1)

	e := errors.Unwrap(err2)
	fmt.Printf("%+v", e)

}
Output:
error 1

func With

func With(err error, args ...interface{}) error

With adds args to err if err is of type Error, othwerwise it creates a new error of type Error and adds args on that error. Passing in a regular error (not errors.Error) to the err argument will convert the error to errors.Error therefore trying to compare errors with Is() will return FALSE.

Types

type Error

type Error struct {
	Msg   string `json:"msg"`
	Stack Stack  `json:"stack"`
	Meta  Meta   `json:"meta"`
	// contains filtered or unexported fields
}

func Flatten

func Flatten(err error) (ret []Error)

Flatten returns a slice of Error from embedded err.

func (Error) As

func (e Error) As(target interface{}) bool

func (*Error) Error

func (e *Error) Error() string

Error returns the error message and satisfies the stdlib Error interface.

func (Error) Is

func (e Error) Is(target error) bool

func (*Error) MarshalJSON added in v0.2.0

func (e *Error) MarshalJSON() ([]byte, error)

func (*Error) PrettyPrint

func (e *Error) PrettyPrint() string

PrettyPrint will recursively print all embedded errors including all information on the error it can found. This should be used in development.

Example
package main

import (
	"fmt"
	"github.com/primalskill/errors"
)

func main() {
	err := errors.E("my error", errors.WithMeta("key", "value"))

	var e *errors.Error
	errors.As(err, &e)

	fmt.Printf("%s", e.PrettyPrint())
}

func (*Error) Unwrap

func (e *Error) Unwrap() error

Unwrap returns the error one level deep otherwise nil. This is a proxy method for Unwrap().

type Meta

type Meta map[string]interface{}

Meta holds extra meta data around an error. Try adding simple values to the Meta map. Key order is not guaranteed.

func GetMeta

func GetMeta(err error) (Meta, bool)

GetMeta returns a Meta map or an empty Meta if the error doesn't contain a Meta or the error is not of type errors.Error. The second returned argument is TRUE if the err has a Meta, FALSE otherwise.

func WithMeta

func WithMeta(firstKey string, args ...interface{}) (m Meta)

WithMeta accepts an even number of arguments representing key/value pairs. The first argument "firstKey" forces the compiler to fail if the first argument is not a string. In "args" every odd argument must be of type string which will be used as the Meta map key. If an odd argument is not a string that pair will be skipped.

Example
package main

import (
	"fmt"
	"github.com/primalskill/errors"
)

func main() {
	// Valid
	mValid := errors.WithMeta("key1", 158, "key2", "some value", "anotherKey", true)

	fmt.Printf("%#v", mValid)

	// Invalid Outputs
	// errors.WithMeta(15) <-- results in compile error
	// errors.WithMeta("noValueKey") <-- returns empty Meta map because there is no value added to noValueKey
	// errors.WithMeta("key1", "value 1", 16, "key3", "key4", "some value") <-- skips 16 and key3 pairs because 16 is int and not string.
	// errors.WithMeta("key1", "val1", 10, "val2", "key3") <-- skips 10 and val2 pairs, output: [key1:val1 key3:]

}
Output:
errors.Meta{"anotherKey":true, "key1":158, "key2":"some value"}
Example (EmptyValue)
package main

import (
	"fmt"
	"github.com/primalskill/errors"
)

func main() {
	mValid := errors.WithMeta("key1", "value1", "key2")
	fmt.Printf("%#v", mValid)
}

func (Meta) Merge

func (p Meta) Merge(firstKey string, args ...interface{}) (m Meta)

Merge combines the arguments to an existing Meta and returns it. Existing keys will be overwritten.

Example
package main

import (
	"fmt"
	"github.com/primalskill/errors"
)

func main() {
	m := errors.WithMeta("key1", "val1")
	m = m.Merge("key2", "val2")

	fmt.Printf("%#v", m)

}
Output:
errors.Meta{"key1":"val1", "key2":"val2"}

func (Meta) Set

func (p Meta) Set(key string, value interface{}) (m Meta)

Set will set key to value and returns Meta. Same keys will be overwritten.

func (Meta) String

func (p Meta) String() string

String returns Meta in [key1:val1 key2:val2 ...] format and satisfies the fmt.Stringer interface.

type Stack

type Stack string

Stack represents an error stack captuing the file path and line number where the error happened in the format <file path>:<line nunmber>. A Stack is always attached to an error automatically.

Jump to

Keyboard shortcuts

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