Documentation ¶
Overview ¶
Example (Printf) ¶
package main import ( "fmt" "os" "strings" "github.com/sumup-oss/go-pkgs/errors" ) func main() { fooError := errors.New("foo") barError := errors.Hide(fooError, "bar") bazError := errors.Hide(barError, "baz") quxError := errors.Wrap(bazError, "qux") fmt.Println("String:") fmt.Printf("%s\n", quxError) fmt.Println() fmt.Println("Verbose:") fmt.Printf("%v\n", quxError) fmt.Println() // Only +v will go trough the Hide barriers and print the whole error chain. fmt.Println("Verbose with stacktrace:") curDir, _ := os.Getwd() output := fmt.Sprintf("%+v\n", quxError) // Clean base path for Output test. fmt.Print(strings.ReplaceAll(output, curDir, "/path")) }
Output: String: qux Verbose: qux: baz Verbose with stacktrace: qux: github.com/sumup-oss/go-pkgs/errors_test.Example_printf /path/example_printf_test.go:15 - baz: github.com/sumup-oss/go-pkgs/errors_test.Example_printf /path/example_printf_test.go:14 - bar: github.com/sumup-oss/go-pkgs/errors_test.Example_printf /path/example_printf_test.go:13 - foo: github.com/sumup-oss/go-pkgs/errors_test.Example_printf /path/example_printf_test.go:12
Index ¶
- func As(err error, target interface{}) bool
- func Hide(err error, format string, a ...interface{}) error
- func HideError(err error, wrapper error) error
- func Is(err, target error) bool
- func New(format string, a ...interface{}) error
- func Propagate(err error) error
- func Unwrap(err error) error
- func UnwrapHidden(err error) error
- func Wrap(err error, format string, a ...interface{}) error
- func WrapError(err error, wrapper error) error
- type Frame
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func As ¶
As is just a wrapper of the standard As.
Example ¶
package main import ( "fmt" "github.com/sumup-oss/go-pkgs/errors" ) type AsCustomError struct { msg string code int } func NewAsCustomError(msg string, code int) error { return &AsCustomError{ msg: msg, code: code, } } func (e *AsCustomError) Error() string { return fmt.Sprintf("[%d] %s", e.code, e.msg) } func (e *AsCustomError) Message() string { return e.msg } func (e *AsCustomError) Code() int { return e.code } func main() { fooError := NewAsCustomError("foo", 1) barError := errors.Wrap(fooError, "bar") bazError := errors.New("baz") quxError := errors.WrapError(barError, bazError) err := quxError var customErr *AsCustomError if errors.As(err, &customErr) { fmt.Printf("msg: %s, code: %d", customErr.Message(), customErr.Code()) } else { fmt.Println("no customErr found") } }
Output: msg: foo, code: 1
Example (WithHide) ¶
package main import ( "fmt" "github.com/sumup-oss/go-pkgs/errors" ) type AsWithHideCustomError struct { msg string code int } func NewAsWithHideCustomError(msg string, code int) error { return &AsWithHideCustomError{ msg: msg, code: code, } } func (e *AsWithHideCustomError) Error() string { return fmt.Sprintf("[%d] %s", e.code, e.msg) } func (e *AsWithHideCustomError) Message() string { return e.msg } func (e *AsWithHideCustomError) Code() int { return e.code } func main() { fooError := NewAsWithHideCustomError("foo", 1) barError := errors.Hide(fooError, "bar") // Since Unwrap will stop here, As cannot find foo. bazError := errors.New("baz") quxError := errors.WrapError(barError, bazError) err := quxError var customErr *AsWithHideCustomError if errors.As(err, &customErr) { fmt.Printf("msg: %s, code: %d", customErr.Message(), customErr.Code()) } else { fmt.Println("no customErr found") } }
Output: no customErr found
func Hide ¶
Hide creates a new error wrapping the err, but the err will not be discoverable with Unwrap calls.
This means that Is and As will not be able to detect any older error in the chain.
Nevertheless the wrapped err and all older errors in the chain are discoverable by using UnwrapHidden calls, meaning that the stacktrace (frame info) is accessible.
Example ¶
package main import ( "fmt" "github.com/sumup-oss/go-pkgs/errors" ) func main() { fooError := errors.New("foo") barError := errors.Hide(fooError, "bar") // Unwrap will stop here, foo won't be discoverable bazError := errors.Wrap(barError, "baz") quxError := errors.Wrap(bazError, "qux") err := quxError for err != nil { fmt.Println(err.Error()) err = errors.Unwrap(err) } }
Output: qux baz bar
func HideError ¶
HideError creates a new error wrapping the err with provided wrapper, but the err will not be discoverable with Unwrap calls.
This can be useful if you want to hide an error with sentinel error.
This means that Is and As will not be able to detect any older error in the chain.
Nevertheless the wrapped err and all older errors in the chain are discoverable by using UnwrapHidden calls, meaning that the stacktrace (frame info) is accessible.
Example ¶
package main import ( "fmt" "github.com/sumup-oss/go-pkgs/errors" ) func main() { internalError := errors.New("internal") apiError := errors.New("api error") // Unwrap will stop here, internalError won't be discoverable barError := errors.HideError(internalError, apiError) bazError := errors.Wrap(barError, "baz") quxError := errors.Wrap(bazError, "qux") err := quxError for err != nil { fmt.Println(err.Error()) err = errors.Unwrap(err) } }
Output: qux baz api error
func Is ¶
Is is just a wrapper of the standard Is.
Example ¶
package main import ( "fmt" "github.com/sumup-oss/go-pkgs/errors" ) func main() { fooError := errors.New("foo") barError := errors.Hide(fooError, "bar") // Since Unwrap will stop here, Is cannot find foo. bazError := errors.New("baz") quxError := errors.WrapError(barError, bazError) quuxError := errors.Wrap(quxError, "quux") err := quuxError if errors.Is(err, quuxError) { fmt.Println("quux found") } if errors.Is(err, quxError) { fmt.Println("qux found") } if errors.Is(err, bazError) { fmt.Println("baz found") } if errors.Is(err, barError) { fmt.Println("bar found") } if !errors.Is(err, fooError) { fmt.Println("foo NOT found") } }
Output: quux found qux found baz found bar found foo NOT found
func New ¶
Creates a new error.
It can be used for creating sentinel errors, or as a replacement of the standard fmt.Errorf calls.
NOTE: New does not support the standard %w error wrapping. Use Wrap, WrapError, Hide and HideError instead.
Example ¶
package main import ( "fmt" "github.com/sumup-oss/go-pkgs/errors" ) var ( NotFoundErr = errors.New("not found error") // Sentinel error created with New. ) func main() { fooErr := errors.Wrap(NotFoundErr, "foo failed") fmt.Printf("%v\n", fooErr) internalError := errors.New("internal failure code=%d", 500) barErr := errors.HideError(internalError, NotFoundErr) fmt.Printf("%v\n", barErr) }
Output: foo failed: not found error not found error
func Propagate ¶
Propagate creates a new error from existing error, by wrapping it with stack trace information.
Most of the time users should use Wrap, WrapError, Hide and HideError.
But sometimes the error does not need wrapping, since it contains enough context. And wrapping will create a chain of two errors with the same description (example: "foo failed: foo failed"). All it is needed is a stack trace. Propagate does exactly that, it just adds a stack trace.
Example ¶
package main import ( "fmt" "os" "strings" "github.com/sumup-oss/go-pkgs/errors" ) func main() { fooError := errors.New("foo failed") // Creating error with stack trace without a wrapping string. barErr := errors.Propagate(fooError) curDir, _ := os.Getwd() output := fmt.Sprintf("%+v\n", barErr) // Clean base path for the Output test. fmt.Print(strings.ReplaceAll(output, curDir, "/path")) }
Output: foo failed: github.com/sumup-oss/go-pkgs/errors_test.ExamplePropagate /path/propagate_example_test.go:15 - foo failed: github.com/sumup-oss/go-pkgs/errors_test.ExamplePropagate /path/propagate_example_test.go:12
func Unwrap ¶
Unwrap is just a wrapper of the standard Unwrap.
Example ¶
package main import ( "fmt" "github.com/sumup-oss/go-pkgs/errors" ) func main() { fooError := errors.New("foo") barError := errors.Hide(fooError, "bar") // Unwrap will stop here, foo won't be discoverable. bazError := errors.Wrap(barError, "baz") quxError := errors.Wrap(bazError, "qux") err := quxError for err != nil { fmt.Println(err.Error()) err = errors.Unwrap(err) } }
Output: qux baz bar
func UnwrapHidden ¶
UnwrapHidden works the same way as Unwrap, but instead of using method Unwrap, it expects method called UnwrapHidden.
This "duplication" is required in order to support the error hiding feature. When an error is created with Hide and HideError functions, the Unwrap loop will stop to the current error and all older errors in the chain will not be discoverable with Unwrap. On the other hand they will continue to be discoverable with UnwrapHidden, which makes it possible to extract the full stacktrace (frame info) even if the error is hiding older errors.
Example ¶
package main import ( "fmt" "github.com/sumup-oss/go-pkgs/errors" ) func main() { fooError := errors.New("foo") barError := errors.Hide(fooError, "bar") // UnwrapHidden will NOT stop here, foo will be discoverable. bazError := errors.Wrap(barError, "baz") quxError := errors.Wrap(bazError, "qux") err := quxError for err != nil { fmt.Println(err.Error()) err = errors.UnwrapHidden(err) } }
Output: qux baz bar foo
func Wrap ¶
Wrap creates a new error wrapping the err. If the err is nil it will return nil.
Example ¶
package main import ( "fmt" "github.com/sumup-oss/go-pkgs/errors" ) func main() { fooError := errors.New("foo") barError := errors.Hide(fooError, "bar") // Unwrap will stop here, foo won't be discoverable bazError := errors.New("baz") quxError := errors.WrapError(barError, bazError) quuxError := errors.Wrap(quxError, "quux") err := quuxError for err != nil { fmt.Println(err.Error()) err = errors.Unwrap(err) } }
Output: quux baz bar
func WrapError ¶
WrapError creates a new error wrapping the err with the provided wrapper.
This can be useful if you want to wrap an error with a sentinel error.
Example ¶
package main import ( "fmt" "github.com/sumup-oss/go-pkgs/errors" ) func main() { internalError := errors.New("internal") apiError := errors.New("api error") barError := errors.WrapError(internalError, apiError) bazError := errors.Wrap(barError, "baz") quxError := errors.Wrap(bazError, "qux") err := quxError for err != nil { fmt.Println(err.Error()) err = errors.Unwrap(err) } }
Output: qux baz api error internal
Types ¶
type Frame ¶
type Frame struct {
// contains filtered or unexported fields
}
Frame is a frame from the call stack, that can report the call location.
func Caller ¶
Caller returns a Frame from the call stack.
The argument skip is the number of stack frames to ascend, with 0 identifying the caller of Caller.
Example ¶
package main import ( "fmt" "os" "strings" "github.com/sumup-oss/go-pkgs/errors" ) func main() { curDir, _ := os.Getwd() frame := errors.Caller(0) function, file, line := frame.Location() fmt.Println(function) fmt.Println(strings.ReplaceAll(file, curDir, "/path")) // Clean base path for Output test. fmt.Println(line) }
Output: github.com/sumup-oss/go-pkgs/errors_test.ExampleCaller /path/frame_example_test.go 14
func (*Frame) Location ¶
Location reports the file, line, and function of a frame.
Example ¶
package main import ( "fmt" "os" "strings" "github.com/sumup-oss/go-pkgs/errors" ) func main() { curDir, _ := os.Getwd() frame := errors.Caller(0) function, file, line := frame.Location() fmt.Println(function) fmt.Println(strings.ReplaceAll(file, curDir, "/path")) // Clean base path for output test. fmt.Println(line) }
Output: github.com/sumup-oss/go-pkgs/errors_test.ExampleFrame_Location /path/frame_example_test.go 31