errors

package module
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Dec 31, 2019 License: MIT Imports: 5 Imported by: 33

README

go-errors

GoDoc This is a library for handling errors in Go language.

master Build Status Tests coverage
dev Build Status Tests coverage

Usage

This package combines Go 1.13's errors package and github.com/pkg/errors.

All funcs from both packages are available.

On top of them, I added some sentinels for common errors I need all the time.

All sentinels are from the same type which contains various information. Whenever a sentinel is used, a StackTrace is also generated.

Here is how to use the errors:

func findme(stuff map[string]string, key string) (string, error) {
    if value, found := stuff[key]; found {
        return value, nil
    }
    return "", errors.NotFoundError.WithWhat(key)
}

func main() {
    var allstuff[string]string
    //...
    value, err := findme("key1")
    if errors.Is(err, errors.NotFoundError) {
        fmt.Fprintf(os.Stderr, "Error: %+v", err)
        // This should print the error its wrapped content and a StackTrace.
    }
}

If you plan to do something with the content of the error, you would try that:

func main() {
    var allstuff[string]string
    //...
    value, err := findme("key1")
    if errors.Is(err, errors.NotFoundError) {
        var details *errors.Error
        if errors.As(err, &details) {
            fmt.Fprintf(os.Stderr, "Could not find %s", details.What)
        }
    }
}

To return an HTTP Status as an error, you could do this:

func doit() error {
    req, err := http.NewRequest(http.MethodGet, "http://www.acme.org")
    if err != nil {
        return errors.WithStack(err)
    }
    httpclient := http.DefaultClient()
    res, err := httpclient.Do(req)
    if err != nil {
        return errors.WithStack(err)
    }
    if res.StatusCode >= 400 {
        return errors.FromHTTPStatusCode(res.StatusCode)
    }
    return nil
}

func main() {
    err := doit()
    if (errors.Is(err, errors.HTTPBadRequest)) {
        // do something
    }
    // do something else
}

Documentation

Overview

This package combines Go 1.13's errors package (https://golang.org/pkg/errors) and github.com/pkg/errors(https://github.com/pkg/errors).

All funcs from both packages are available.

On top of them, I added some sentinels for common errors I need all the time.

All sentinels are from the same type which contains various information. Whenever a sentinel is used, a StackTrace is also generated.

Here is how to use the errors:

func findme(stuff map[string]string, key string) (string, error) {
    if value, found := stuff[key]; found {
        return value, nil
    }
    return "", errors.NotFoundError.WithWhat(key)
}

func main() {
    var allstuff[string]string
    //...
    value, err := findme("key1")
    if errors.Is(err, errors.NotFoundError) {
        fmt.Fprintf(os.Stderr, "Error: %+v", err)
        // This should print the error its wrapped content and a StackTrace.
    }
}

If you plan to do something with the content of the error, you would try that:

func main() {
    var allstuff[string]string
    //...
    value, err := findme("key1")
    if errors.Is(err, errors.NotFoundError) {
        var details *errors.Error
        if errors.As(err, &details) {
            fmt.Fprintf(os.Stderr, "Could not find %s", details.What)
        }
    }
}

Index

Examples

Constants

This section is empty.

Variables

View Source
var ArgumentInvalidError = NewSentinel(http.StatusBadRequest, "error.argument.invalid", "Argument %s is invalid (value: %v)")

ArgumentInvalidError is used when an argument has an unexpected value

View Source
var ArgumentMissingError = NewSentinel(http.StatusBadRequest, "error.argument.missing", "Argument %s is missing")

ArgumentMissingError is used when an argument is missing

View Source
var EnvironmentInvalidError = NewSentinel(http.StatusBadRequest, "error.environment.invalid", "Environment variable %s is invalid (value: %v)")

EnvironmentInvalidError is used when an argument has an unexpected value

View Source
var EnvironmentMissingError = NewSentinel(http.StatusBadRequest, "error.environment.missing", "Environment variable %s is missing")

EnvironmentMissingError is used when an argument is missing

View Source
var FoundError = NewSentinel(http.StatusFound, "error.found", "%s %s Found")

FoundError is used when something is found but it should not have been

View Source
var HTTPBadGatewayError = NewSentinel(http.StatusBadGateway, http.StatusText(http.StatusBadGateway), "error.http.gateway")

********** HTTP Errors ************************************************************************************************************** HTTPBadGatewayError is used when an http.Client request fails

View Source
var HTTPBadRequestError = NewSentinel(http.StatusBadRequest, http.StatusText(http.StatusBadRequest)+". %s", "error.http.request")

HTTPBadRequestError is used when an http.Client request fails

View Source
var HTTPForbiddenError = NewSentinel(http.StatusForbidden, http.StatusText(http.StatusForbidden), "error.http.forbidden")

HTTPForbiddenError is used when an http.Client request fails

View Source
var HTTPInternalServerError = NewSentinel(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError), "error.http.server")

HTTPInternalServerError is used when an http.Client request fails

View Source
var HTTPMethodNotAllowedError = NewSentinel(http.StatusMethodNotAllowed, http.StatusText(http.StatusMethodNotAllowed), "error.http.notallowed")

HTTPMethodNotAllowedError is used when an http.Client request fails

View Source
var HTTPNotFoundError = NewSentinel(http.StatusNotFound, http.StatusText(http.StatusNotFound), "error.http.notfound")

HTTPNotFoundError is used when an http.Client request fails

View Source
var HTTPNotImplementedError = NewSentinel(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented), "error.http.notimplemented")

HTTPNotImplementedError is used when an http.Client request fails

View Source
var HTTPServiceUnavailableError = NewSentinel(http.StatusServiceUnavailable, http.StatusText(http.StatusServiceUnavailable), "error.http.unavailable")

HTTPServiceUnavailableError is used when an http.Client request fails

View Source
var HTTPStatusConflictError = NewSentinel(http.StatusConflict, http.StatusText(http.StatusConflict), "error.http.conflict")

HTTPStatusConflictError reports HTTP Error StatusConflict

View Source
var HTTPStatusExpectationFailedError = NewSentinel(http.StatusExpectationFailed, http.StatusText(http.StatusExpectationFailed), "error.http.expectation.failed")

HTTPStatusExpectationFailedError reports HTTP Error StatusExpectationFailed

View Source
var HTTPStatusFailedDependencyError = NewSentinel(http.StatusFailedDependency, http.StatusText(http.StatusFailedDependency), "error.http.failed.dependency")

HTTPStatusFailedDependencyError reports HTTP Error StatusFailedDependency

View Source
var HTTPStatusGatewayTimeoutError = NewSentinel(http.StatusGatewayTimeout, http.StatusText(http.StatusGatewayTimeout), "error.http.gateway.timeout")

HTTPStatusGatewayTimeoutError reports HTTP Error StatusGatewayTimeout

View Source
var HTTPStatusGoneError = NewSentinel(http.StatusGone, http.StatusText(http.StatusGone), "error.http.gone")

HTTPStatusGoneError reports HTTP Error StatusGone

View Source
var HTTPStatusHTTPVersionNotSupportedError = NewSentinel(http.StatusHTTPVersionNotSupported, http.StatusText(http.StatusHTTPVersionNotSupported), "error.http.unsupported.version")

HTTPStatusHTTPVersionNotSupportedError reports HTTP Error StatusHTTPVersionNotSupported

View Source
var HTTPStatusInsufficientStorageError = NewSentinel(http.StatusInsufficientStorage, http.StatusText(http.StatusInsufficientStorage), "error.http.storage.insufficient")

HTTPStatusInsufficientStorageError reports HTTP Error StatusInsufficientStorage

View Source
var HTTPStatusLengthRequiredError = NewSentinel(http.StatusLengthRequired, http.StatusText(http.StatusLengthRequired), "error.http.length.required")

HTTPStatusLengthRequiredError reports HTTP Error StatusLengthRequired

View Source
var HTTPStatusLockedError = NewSentinel(http.StatusLocked, http.StatusText(http.StatusLocked), "error.http.locked")

HTTPStatusLockedError reports HTTP Error StatusLocked

View Source
var HTTPStatusLoopDetectedError = NewSentinel(http.StatusLoopDetected, http.StatusText(http.StatusLoopDetected), "error.http.loop.detected")

HTTPStatusLoopDetectedError reports HTTP Error StatusLoopDetected

View Source
var HTTPStatusMisdirectedRequestError = NewSentinel(http.StatusMisdirectedRequest, http.StatusText(http.StatusMisdirectedRequest), "error.http.misdirect.request")

HTTPStatusMisdirectedRequestError reports HTTP Error StatusMisdirectedRequest

View Source
var HTTPStatusNetworkAuthenticationRequiredError = NewSentinel(http.StatusNetworkAuthenticationRequired, http.StatusText(http.StatusNetworkAuthenticationRequired), "error.http.network.authentication.required")

HTTPStatusNetworkAuthenticationRequiredError reports HTTP Error StatusNetworkAuthenticationRequired

View Source
var HTTPStatusNotAcceptableError = NewSentinel(http.StatusNotAcceptable, http.StatusText(http.StatusNotAcceptable), "error.http.notacceptable")

HTTPStatusNotAcceptableError reports HTTP Error StatusNotAcceptable

View Source
var HTTPStatusNotExtendedError = NewSentinel(http.StatusNotExtended, http.StatusText(http.StatusNotExtended), "error.http.notextended")

HTTPStatusNotExtendedError reports HTTP Error StatusNotExtended

View Source
var HTTPStatusPaymentRequiredError = NewSentinel(http.StatusPaymentRequired, http.StatusText(http.StatusPaymentRequired), "error.http.payment.required")

HTTPStatusPaymentRequiredError reports HTTP Error StatusPaymentRequired

View Source
var HTTPStatusPreconditionFailedError = NewSentinel(http.StatusPreconditionFailed, http.StatusText(http.StatusPreconditionFailed), "error.http.precondition.failed")

HTTPStatusPreconditionFailedError reports HTTP Error StatusPreconditionFailed

View Source
var HTTPStatusPreconditionRequiredError = NewSentinel(http.StatusPreconditionRequired, http.StatusText(http.StatusPreconditionRequired), "error.precondition.required")

HTTPStatusPreconditionRequiredError reports HTTP Error StatusPreconditionRequired

View Source
var HTTPStatusProxyAuthRequiredError = NewSentinel(http.StatusProxyAuthRequired, http.StatusText(http.StatusProxyAuthRequired), "error.http.proxy.authentication.required")

HTTPStatusProxyAuthRequiredError reports HTTP Error StatusProxyAuthRequired

View Source
var HTTPStatusRequestEntityTooLargeError = NewSentinel(http.StatusRequestEntityTooLarge, http.StatusText(http.StatusRequestEntityTooLarge), "error.http.request.entity.toolarge")

HTTPStatusRequestEntityTooLargeError reports HTTP Error StatusRequestEntityTooLarge

View Source
var HTTPStatusRequestHeaderFieldsTooLargeError = NewSentinel(http.StatusRequestHeaderFieldsTooLarge, http.StatusText(http.StatusRequestHeaderFieldsTooLarge), "error.http.request.fields.toolarge")

HTTPStatusRequestHeaderFieldsTooLargeError reports HTTP Error StatusRequestHeaderFieldsTooLarge

View Source
var HTTPStatusRequestTimeoutError = NewSentinel(http.StatusRequestTimeout, http.StatusText(http.StatusRequestTimeout), "error.http.request.timeout")

HTTPStatusRequestTimeoutError reports HTTP Error StatusRequestTimeout

View Source
var HTTPStatusRequestURITooLongError = NewSentinel(http.StatusRequestURITooLong, http.StatusText(http.StatusRequestURITooLong), "error.http.request.uri.toolong")

HTTPStatusRequestURITooLongError reports HTTP Error StatusRequestURITooLong

View Source
var HTTPStatusRequestedRangeNotSatisfiableError = NewSentinel(http.StatusRequestedRangeNotSatisfiable, http.StatusText(http.StatusRequestedRangeNotSatisfiable), "error.http.request.range.notstatisfiable")

HTTPStatusRequestedRangeNotSatisfiableError reports HTTP Error StatusRequestedRangeNotSatisfiable

View Source
var HTTPStatusTeapotError = NewSentinel(http.StatusTeapot, http.StatusText(http.StatusTeapot), "error.http.teapot")

HTTPStatusTeapotError reports HTTP Error StatusTeapot

View Source
var HTTPStatusTooEarlyError = NewSentinel(http.StatusTooEarly, http.StatusText(http.StatusTooEarly), "error.http.tooearly")

HTTPStatusTooEarlyError reports HTTP Error StatusTooEarly

View Source
var HTTPStatusTooManyRequestsError = NewSentinel(http.StatusTooManyRequests, http.StatusText(http.StatusTooManyRequests), "error.http.request.toomany")

HTTPStatusTooManyRequestsError reports HTTP Error StatusTooManyRequests

View Source
var HTTPStatusUnavailableForLegalReasonsError = NewSentinel(http.StatusUnavailableForLegalReasons, http.StatusText(http.StatusUnavailableForLegalReasons), "error.http.unavailable")

HTTPStatusUnavailableForLegalReasonsError reports HTTP Error StatusUnavailableForLegalReasons

View Source
var HTTPStatusUnprocessableEntityError = NewSentinel(http.StatusUnprocessableEntity, http.StatusText(http.StatusUnprocessableEntity), "error.http.entity.unprocessable")

HTTPStatusUnprocessableEntityError reports HTTP Error StatusUnprocessableEntity

View Source
var HTTPStatusUnsupportedMediaTypeError = NewSentinel(http.StatusUnsupportedMediaType, http.StatusText(http.StatusUnsupportedMediaType), "error.http.mediatype.unsupported")

HTTPStatusUnsupportedMediaTypeError reports HTTP Error StatusUnsupportedMediaType

View Source
var HTTPStatusUpgradeRequiredError = NewSentinel(http.StatusUpgradeRequired, http.StatusText(http.StatusUpgradeRequired), "error.http.upgrade.required")

HTTPStatusUpgradeRequiredError reports HTTP Error StatusUpgradeRequired

View Source
var HTTPStatusUseProxyError = NewSentinel(http.StatusUseProxy, http.StatusText(http.StatusUseProxy), "error.http.proxy.required")

HTTPStatusUseProxyError reports HTTP Error StatusUseProxy

View Source
var HTTPStatusVariantAlsoNegotiatesError = NewSentinel(http.StatusVariantAlsoNegotiates, http.StatusText(http.StatusVariantAlsoNegotiates), "error.http.variant.alsonegotiate")

HTTPStatusVariantAlsoNegotiatesError reports HTTP Error StatusVariantAlsoNegotiates

View Source
var HTTPUnauthorizedError = NewSentinel(http.StatusUnauthorized, http.StatusText(http.StatusUnauthorized), "error.http.unauthorized")

HTTPUnauthorizedError is used when an http.Client request fails

View Source
var JSONMarshalError = NewSentinel(http.StatusBadRequest, "error.json.marshal", "JSON failed to marshal data")

JSONMarshalError is used when data failed to be marshaled into JSON

View Source
var JSONPropertyMissingError = NewSentinel(http.StatusBadRequest, "error.json.property.missing", "JSON data is missing property %s")

JSONPropertyMissingError is used when JSON data is missing a property

View Source
var JSONUnmarshalError = NewSentinel(http.StatusBadRequest, "error.json.unmarshal", "JSON failed to unmarshal data")

JSONUnmarshalError is used when JSON data is missing a property

View Source
var NotFoundError = NewSentinel(http.StatusNotFound, "error.notfound", "%s %s Not Found")

NotFoundError is used when something is not found

View Source
var NotImplementedError = NewSentinel(http.StatusNotImplemented, "error.notimplemented", "Not Implemented")

NotImplementedError is used when some code/method/func is not written yet

View Source
var TooManyError = NewSentinel(http.StatusInternalServerError, "error.toomany", "Too Many")

TooManyError is used when something is found too many times

View Source
var UnknownError = NewSentinel(http.StatusInternalServerError, "error.unknown", "Unknown Error: %s")

UnknownError is used when the code does not know which error it is facing...

View Source
var UnsupportedError = NewSentinel(http.StatusMethodNotAllowed, "error.unsupported", "Unsupported %s: %s")

UnsupportedError is used when something is unsupported by the code

View Source
var VERSION = "0.0.1" + commit

VERSION is the version of this application

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.

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.

As will panic if target is not a non-nil pointer to either a type that implements error, or to any interface type. As returns false if err is nil.

func Errorf

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

Errorf formats according to a format specifier and returns the string as a value that satisfies error. Errorf also records the stack trace at the point it was called.

func FromHTTPStatusCode

func FromHTTPStatusCode(code int) error

FromHTTPStatusCode creates a new error of the sentinel that matches the given HTTP status code it also records the stack trace at the point it was called.

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.

func New

func New(message string) error

New returns a new error with the supplied message New also records the stack trace at the point it was called.

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.

func WithMessage

func WithMessage(err error, message string) error

WithMessage annotates err with a new message. If err is nil, WithMessage returns nil.

func WithMessagef

func WithMessagef(err error, format string, args ...interface{}) error

WithMessagef annotates err with the format specifier. If err is nil, WithMessagef returns nil.

func WithStack

func WithStack(err error) error

WithStack annotates err with a stack trace at the point WithStack was called. If err is nil, WithStack returns nil.

func Wrap

func Wrap(err error, message string) error

Wrap returns an error annotating err with a stack trace at the point Wrap is called, and the supplied message. If err is nil, Wrap returns nil.

func Wrapf

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

Wrapf returns an error annotating err with a stack trace at the point Wrapf is called, and the format specifier. If err is nil, Wrapf returns nil.

Types

type Error

type Error struct {
	// Code is an numerical code, like an HTTP Status Code
	Code int `json:"code"`
	// ID is the string identifier, like: "error.argument.invalid"
	ID string `json:"id"`
	// Text is the human readable error message
	Text string `json:"text"`
	// What contains what element is wrong for errors that need it, like NotFoundError
	What string `json:"what,omitempty"`
	// Value contains the value that was wrong for errros that need it, like ArgumentInvalidError
	Value interface{} `json:"value"`
	// Cause contains the error that caused this error (to wrap a json error in a JSONMarshalError, for example)
	Cause error
}

Error describes an augmented implementation of Go's error interface

Example
sentinel := errors.NewSentinel(500, "error.test.custom", "Test Error")
err := sentinel.New()
if err != nil {
	fmt.Println(err)

	var details *errors.Error
	if errors.As(err, &details) {
		fmt.Println(details.ID)
	}
}
Output:

Test Error
error.test.custom

func NewSentinel

func NewSentinel(code int, id, message string) *Error

NewSentinel creates a new sentinel a sentinel is an Error that hasn't been decorated with a stack trace

Typically, it can be used to create error that can be matched later

func (Error) Error

func (e Error) Error() string

Error returns the string version of this error

func (Error) Is

func (e Error) Is(target error) bool

Is tells if this error matches the target

func (Error) New

func (e Error) New() error

New creates a new instance of this error New also records the stack trace at the point it was called.

func (Error) Unwrap

func (e Error) Unwrap() error

Unwrap gives the Cause of this Error, if any

func (Error) WithMessage

func (e Error) WithMessage(message string) error

WithMessage annotates a new instance of this error with a new message. If err is nil, WithMessage returns nil.

WithMessage also records the stack trace at the point it was called.

Example
sentinel := errors.NewSentinel(500, "error.test.custom", "Test Error")
err := sentinel.WithMessage("hmmm... this is bad")
if err != nil {
	fmt.Println(err)

	var details *errors.Error
	if errors.As(err, &details) {
		fmt.Println(details.ID)
	}
}
Output:

hmmm... this is bad: Test Error
error.test.custom

func (*Error) WithWhat

func (e *Error) WithWhat(what string) error

WithWhat creates a new error from a given sentinal telling "What" is wrong

Example
err := errors.ArgumentMissingError.WithWhat("key")
if err != nil {
	fmt.Println(err)

	var details *errors.Error
	if errors.As(err, &details) {
		fmt.Println(details.ID)
	}
}
Output:

Argument key is missing
error.argument.missing

func (*Error) WithWhatAndValue

func (e *Error) WithWhatAndValue(what string, value interface{}) error

WithWhatAndValue creates a new error from a given sentinal telling "What" is wrong and the wrong value

Example
err := errors.ArgumentInvalidError.WithWhatAndValue("key", "value")
if err != nil {
	fmt.Println(err)

	var details *errors.Error
	if errors.As(err, &details) {
		fmt.Println(details.ID)
	}
}
Output:

Argument key is invalid (value: value)
error.argument.invalid
Example (Array)
err := errors.ArgumentInvalidError.WithWhatAndValue("key", []string{"value1", "value2"})
if err != nil {
	fmt.Println(err)

	var details *errors.Error
	if errors.As(err, &details) {
		fmt.Println(details.ID)
	}
}
Output:

Argument key is invalid (value: [value1 value2])
error.argument.invalid

func (Error) Wrap

func (e Error) Wrap(err error) error

Wrap wraps the given error in this Error

Example
var payload struct {
	Value string `json:"value"`
}

err := json.Unmarshal([]byte(`{"value": 0`), &payload)
if err != nil {
	finalerr := errors.JSONMarshalError.Wrap(err)
	var details *errors.Error
	if errors.As(finalerr, &details) {
		fmt.Println(details.ID)
	}

	fmt.Println(finalerr)

	cause := details.Unwrap()
	if cause != nil {
		fmt.Println(cause)
	}
}
Output:

error.json.marshal
JSON failed to marshal data: unexpected end of JSON input
unexpected end of JSON input

type MultiError

type MultiError struct {
	Errors []error
}

MultiError is used to collect errors, like during a loop

Example
err := &errors.MultiError{}
_ = err.Append(errors.New("this is the first error"))
_ = err.Append(errors.New("this is the second error"))
fmt.Println(err)
Output:

2 Errors:
this is the first error
this is the second error

func (*MultiError) Append

func (me *MultiError) Append(err error) *MultiError

Append appends a new error If the error is nil, nothing is added

func (*MultiError) AsError

func (me *MultiError) AsError() error

AsError returns this if it contains errors, nil otherwise

func (*MultiError) Error

func (me *MultiError) Error() string

Error returns the string version of this error

Jump to

Keyboard shortcuts

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