Commit 8f170959 authored by Kirill Smelkov's avatar Kirill Smelkov

xerr += Context, Contextf

This are handy utilities to automatically prepend context on error
return. For example in

	func myfunc(...) (..., err error) {
		defer xerr.Context(&err, "error context")
		...
		if ... {
			return ..., errors.New("an error")
		}
		return ..., nil
	}

while preserving nil error return on successful execution, myfunc will
return error with string "error context: an error" on failure case.
parent c0bbd06e
......@@ -72,3 +72,43 @@ func (errv Errorv) Err() error {
return errv
}
}
// ----------------------------------------
// Context provides error context to be automatically added on error return
// to work as intended it should be called under defer like this:
//
// func myfunc(...) (..., err error) {
// defer xerr.Context(&err, "error context")
// ...
//
// it is also possible to use Context directly to add context to an error if it
// is non-nil:
//
// ..., myerr := f()
// xerr.Context(&myerr, "while doing something")
//
// which is equivalent to
//
// ..., myerr := f()
// if myerr != nil {
// myerr = fmt.Errorf("%s: %s", "while doing something", myerr)
// }
func Context(errp *error, context string) {
if *errp == nil {
return
}
*errp = fmt.Errorf("%s: %s", context, *errp)
}
// Contextf provides formatted error context to be automatically added on error return
// Contextf is formatted analog of Context. Please see Context for details on how to use.
func Contextf(errp *error, format string, argv ...interface{}) {
if *errp == nil {
return
}
format += ": %s"
argv = append(argv, *errp)
*errp = fmt.Errorf(format, argv...)
}
......@@ -63,3 +63,34 @@ func TestErrorv(t *testing.T) {
- err3 "hello world"
`)
}
func TestContext(t *testing.T) {
test := func(e error) (err error) {
defer Context(&err, "test ctx")
return e
}
testf := func(e error) (err error) {
defer Contextf(&err, "testf ctx %d %q", 123, "hello")
return e
}
if test(nil) != nil {
t.Error("Context(nil) -> !nil")
}
if testf(nil) != nil {
t.Error("Contextf(nil) -> !nil")
}
err := errors.New("an error")
want := "test ctx: an error"
if e := test(err); !(e != nil && e.Error() == want) {
t.Errorf("Context(%v) -> %v ; want %v", err, e, want)
}
want = `testf ctx 123 "hello": an error`
if e := testf(err); !(e != nil && e.Error() == want) {
t.Errorf("Contextf(%v) -> %v ; want %v", err, e, want)
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment