errors

package module
v1.1.1 Latest Latest
Warning

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

Go to latest
Published: Jun 12, 2022 License: MIT Imports: 5 Imported by: 12

README

Documentation Go Report Card Build Status codecov

golang package for enhanced errors that capture file and line number information, the call stack, relevant identifiers, and a handle back to the original error for type switching.

Replacement for fmt.Errorf(...):

err := errors.Errorf("Failed to do something; here's a value %v",len(data))
fmt.Printf("%#v\n",err) // Prints full stack trace.

Wrap another function's error:

_, err := net.Dial( "tcp", "localhost:8080" )
if err != nil {
    return errors.Go( err )
}

Obtain the original error in order to type switch:

func connect() error {
    _, err := net.Dial( "tcp", "localhost:0" )
    if err != nil {
        return errors.Go( err )
    }
    return nil
}

err := connect()
switch errors.Original( err ).(type) {
    case *net.OpError:
        // We know the original type!
}

See the godoc link for more information.

Documentation

Overview

Package errors provides enhanced error reporting and specific error types.

This package provides errors with more information about when and where they occurred; the call to Printf will print file name, line number, and stack information.

err := errors.Errorf("An error occurred because len() == %v", len(something))
fmt.Printf("%#v\n",err) // Prints full stack trace.

Go() can wrap an existing error within the Error interface defined in this package.

err := someApi()
if err != nil {
	return errors.Go(err)
}

Utility Methods

For receivers that are pointers:

func (me *Type) Do() error {
	if me == nil {
		return errors.NilReceiver().Type(me)
	}
}

For required arguments that are nil:

func Make( arg *Conf ) (*Type, error) {
	if arg == nil {
		return nil, errors.NilArgument( "arg" ).Type( arg );
	}
}

Original Error

It may be helpful for your error handling code to type switch on the original error when wrapping it within errors.Go(); see documentation and example for Original().

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Is added in v1.1.0

func Is(err error, target error) bool

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

If err is an Error returned from this package then Is() tests the error returned from Original(err).

Internally it calls down to errors.Is() from the standard errors package.

func Original

func Original(err error) interface{}

Original returns a non-nil interface if the incoming type is an Error from this package.

Example
package main

import (
	"fmt"
	"net"

	"github.com/nofeaturesonlybugs/errors"
)

func main() {
	// Demonstrates how to type switch on the original error when using this package.
	var err error

	// This test block ensures type switching works when nil is passed to Original.
	noError := func() error {
		return nil
	}
	err = noError()
	switch errors.Original(err).(type) {
	default:
		fmt.Printf("Works when error is nil.\n")
	}

	// This test block ensures type switching works when the error is Error from this package
	// but has a nil return value for Interface() method.
	errorf := func() error {
		return errors.Errorf("A formatted error!")
	}
	err = errorf()
	switch errors.Original(err).(type) {
	default:
		fmt.Printf("Works when error is error.Error but nil interface.\n")
	}

	// This test block shows the more practical usage of looking for a specifc error.
	netOpError := func() error {
		_, err := net.Dial("blurp", "localhost:0")
		if err != nil {
			return errors.Go(err)
		}
		return nil
	}
	err = netOpError()
	switch errors.Original(err).(type) {
	case *net.OpError:
		fmt.Printf("Got expected *net.OpErr\n")
	default:
		fmt.Printf("Expected *net.OpError; got %T\n", err)
	}

	// This final example shows an unwrapped error is returned as-is by Original.
	netOpErrorUnwrapped := func() error {
		_, err := net.Dial("blurp", "localhost:0")
		return err
	}
	err = netOpErrorUnwrapped()
	if originalErr := errors.Original(err); originalErr == err {
		fmt.Println("Original error returned when unwrapped.")
	}

}
Output:

Works when error is nil.
Works when error is error.Error but nil interface.
Got expected *net.OpErr
Original error returned when unwrapped.

Types

type Error

type Error interface {
	// Error returns a string value of the Error and satisfies built-in error interface.
	Error() string
	// Format implements fmt.Formatter interface; %#v, %+v will print error information plus call stack.
	Format(fmt.State, rune)
	// Interface returns the underlying error in order to support type switching; this allows error types from
	// other packages to be wrapped with Go() but still type switch on the underlying type.
	Interface() interface{}
	// Stack returns slice of Frame objects to represent the stack frame.
	Stack() []Frame
	// Tag adds extra information to the error and returns the type for method chaining.
	Tag(name, value string) Error
	// Type adds a special Tag() with type=%T information.
	Type(interface{}) Error
}

Error is the interface returned by functions in this package.

Example (NilArgument)
package main

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

func main() {
	type T struct{}

	fn := func(arg *T) error {
		if arg == nil {
			return errors.NilArgument("arg").Type(arg)
		}
		return nil
	}

	if err := fn(nil); err != nil {
		fmt.Println(err)
		_ = fmt.Sprintf("%#v", err)
	}
}
Output:

Nil argument; identifier=arg; type=*errors_test.T
Example (NilMember)
package main

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

type B struct {
	V *int
}

func (b *B) DoIt() error {
	if b == nil {
		return errors.NilReceiver()
	} else if b.V == nil {
		return errors.NilMember("V").Type(b.V)
	}
	fmt.Println("Did it!")
	return nil
}

func (b *B) String() (string, error) {
	if b == nil {
		return "", errors.NilReceiver().Type(b)
	}
	return "Hello, World!", nil
}

func main() {
	var b *B

	b = &B{}
	if s, err := b.String(); err != nil {
		fmt.Println(err)
	} else {
		fmt.Println(s)
	}
	if err := b.DoIt(); err != nil {
		fmt.Println(err)
	}

	b = nil
	if s, err := b.String(); err != nil {
		fmt.Println(err)
	} else {
		fmt.Println(s)
	}
}
Output:

Hello, World!
Nil member; member=V; type=*int
Nil receiver; type=*errors_test.B
Example (NilReceiver)
package main

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

type A struct{}

func (a *A) String() (string, error) {
	if a == nil {
		return "", errors.NilReceiver().Type(a)
	}
	return "Hello, World!", nil
}

func main() {
	var a *A

	a = &A{}
	if s, err := a.String(); err != nil {
		fmt.Println(err)
	} else {
		fmt.Println(s)
	}

	a = nil
	if s, err := a.String(); err != nil {
		fmt.Println(err)
	} else {
		fmt.Println(s)
	}
}
Output:

Hello, World!
Nil receiver; type=*errors_test.A

func AlreadyStarted

func AlreadyStarted() Error

AlreadyStarted returns an error representing a service that has already started and can not start again.

func Errorf

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

Errorf is similar to fmt.Errorf except it returns the enhanced Error interface from this package.

func Go

func Go(err error) Error

Go returns an Error if the passed `err` is non-nil; the purpose of this function is to wrap contextual information, such as call stack, to the initial error.

func NilArgument

func NilArgument(ident string) Error

NilArgument creates an error when a function argument is nil.

func MyFunc(a *int) (int, error) {
	if a == nil {
		return 0, NilArgument("a").Type(a)
	}
	return *a, nil
}

func NilMember

func NilMember(ident string) Error

NilMember creates an error when a struct member is nil.

func (me SomeType) DoIt() error {
	if me.member == nil {
		return NilMember("me.member").Type(me.member)
	}
	return nil
}

func NilReceiver

func NilReceiver() Error

NilReceiver creates an error when a receiver is nil.

func (me *SomeType) DoIt() error {
	if me == nil {
		return NilReceiver()
	}
	return nil
}

type Frame

type Frame struct {
	File     string
	Function string
	Line     int
}

Frame is a call stack frame.

func Stack

func Stack() []Frame

Stack returns the call stack frames of the caller.

func (Frame) String

func (me Frame) String() string

String returns the Frame as a string.

Jump to

Keyboard shortcuts

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