Commit 7e9d3221 authored by Kirill Smelkov's avatar Kirill Smelkov

xerr: Convert documentation to Go style + package-level description

I was too used to my old Python habit while originally writing this.
Using the occasion add package-level description which outlines the
package to a user.
parent 66edb630
// Copyright (C) 2015-2017 Nexedi SA and Contributors. // Copyright (C) 2015-2018 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com> // Kirill Smelkov <kirr@nexedi.com>
// //
// This program is free software: you can Use, Study, Modify and Redistribute // This program is free software: you can Use, Study, Modify and Redistribute
...@@ -17,7 +17,48 @@ ...@@ -17,7 +17,48 @@
// See COPYING file for full licensing terms. // See COPYING file for full licensing terms.
// See https://www.nexedi.com/licensing for rationale and options. // See https://www.nexedi.com/licensing for rationale and options.
// Package xerr provides addons for error-handling // Package xerr provides addons for error-handling.
//
//
// Error context
//
// Context and Contextf are handy to concisely add context to returned error,
// for example:
//
// func myfunc(arg1, arg2 string) (..., err error) {
// defer xerr.Contextf(&error, "doing something (%s, %s)", arg1, arg2)
// ...
//
// which will, if returned error is !nil, wrap it with the following prefix:
//
// "doing something (%s, %s):" % (arg1, arg2)
//
// The original unwrapped error will be still accessible as the cause of
// returned error. Please see package github.com/pkg/errors for details on
// this topic.
//
//
// Error vector
//
// Sometimes there are several operations performed and we want to collect
// errors from them all. For this Errorv could be used which is vector of
// errors and at the same time an error itself. After collecting it is possible
// to extract resulting error from the vector in canonical form with
// Errorv.Err. Errorv also provides handy ways to append errors to the vector
// - see Errorv.Append* for details.
//
// For convenience Merge could be used to concisely construct error vector
// from !nil errors and extract its canonical form in one line, for example:
//
// err1 := op1(...)
// err2 := op2(...)
// err3 := op3(...)
//
// err := xerr.Merge(err1, err2, err3)
// return err
//
// There is also First counterpart to Merge, which returns only first !nil
// error.
package xerr package xerr
import ( import (
...@@ -26,9 +67,14 @@ import ( ...@@ -26,9 +67,14 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
) )
// error merging multiple errors (e.g. after collecting them from several parallel workers) // Errorv is error vector merging multiple errors (e.g. after collecting them from several parallel workers).
type Errorv []error type Errorv []error
// Error returns string representation of error vector.
//
// - "" if len(errv)==0
// - errv[0].Error() if len(errv)==1
// - "<n> errors:\n" + string representation of every error on separate line, otherwise.
func (errv Errorv) Error() string { func (errv Errorv) Error() string {
switch len(errv) { switch len(errv) {
case 0: case 0:
...@@ -44,12 +90,12 @@ func (errv Errorv) Error() string { ...@@ -44,12 +90,12 @@ func (errv Errorv) Error() string {
return msg return msg
} }
// append err to error vector // Append appends err to error vector.
func (errv *Errorv) Append(err error) { func (errv *Errorv) Append(err error) {
*errv = append(*errv, err) *errv = append(*errv, err)
} }
// append err to error vector, but only if err != nil // Appendif appends err to error vector if err != nil.
func (errv *Errorv) Appendif(err error) { func (errv *Errorv) Appendif(err error) {
if err == nil { if err == nil {
return return
...@@ -57,15 +103,16 @@ func (errv *Errorv) Appendif(err error) { ...@@ -57,15 +103,16 @@ func (errv *Errorv) Appendif(err error) {
errv.Append(err) errv.Append(err)
} }
// append formatted error string // Appendf appends formatted error string.
func (errv *Errorv) Appendf(format string, a ...interface{}) { func (errv *Errorv) Appendf(format string, a ...interface{}) {
errv.Append(fmt.Errorf(format, a...)) errv.Append(fmt.Errorf(format, a...))
} }
// Err returns error in canonical form accumulated in error vector // Err returns error in canonical form accumulated in error vector.
// - nil if len(errv)==0 //
// - errv[0] if len(errv)==1 // XXX is this good idea? // - nil if len(errv)==0
// - errv otherwise // - errv[0] if len(errv)==1 // XXX is this good idea?
// - errv otherwise
func (errv Errorv) Err() error { func (errv Errorv) Err() error {
switch len(errv) { switch len(errv) {
case 0: case 0:
...@@ -77,11 +124,13 @@ func (errv Errorv) Err() error { ...@@ -77,11 +124,13 @@ func (errv Errorv) Err() error {
} }
} }
// Merge merges non-nil errors into one error // Merge merges non-nil errors into one error.
//
// it returns: // it returns:
// - nil if all errors are nil //
// - single error if there is only one non-nil error // - nil if all errors are nil
// - Errorv with non-nil errors if there is more than one non-nil error // - single error if there is only one non-nil error
// - Errorv with non-nil errors if there is more than one non-nil error
func Merge(errv ...error) error { func Merge(errv ...error) error {
ev := Errorv{} ev := Errorv{}
for _, err := range errv { for _, err := range errv {
...@@ -90,7 +139,7 @@ func Merge(errv ...error) error { ...@@ -90,7 +139,7 @@ func Merge(errv ...error) error {
return ev.Err() return ev.Err()
} }
// First returns first non-nil error, or nil if there is no errors // First returns first non-nil error, or nil if there is no errors.
func First(errv ...error) error { func First(errv ...error) error {
for _, err := range errv { for _, err := range errv {
if err != nil { if err != nil {
...@@ -102,14 +151,15 @@ func First(errv ...error) error { ...@@ -102,14 +151,15 @@ func First(errv ...error) error {
// ---------------------------------------- // ----------------------------------------
// Context provides error context to be automatically added on error return // Context provides error context to be automatically added on error return.
// to work as intended it should be called under defer like this: //
// Intended to be used under defer like this:
// //
// func myfunc(...) (..., err error) { // func myfunc(...) (..., err error) {
// defer xerr.Context(&err, "error context") // defer xerr.Context(&err, "error context")
// ... // ...
// //
// it is also possible to use Context directly to add context to an error if it // It is also possible to use Context directly to add context to an error if it
// is non-nil: // is non-nil:
// //
// ..., myerr := f() // ..., myerr := f()
...@@ -130,7 +180,8 @@ func Context(errp *error, context string) { ...@@ -130,7 +180,8 @@ func Context(errp *error, context string) {
*errp = errors.WithMessage(*errp, context) *errp = errors.WithMessage(*errp, context)
} }
// Contextf provides formatted error context to be automatically added on error return // 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. // Contextf is formatted analog of Context. Please see Context for details on how to use.
func Contextf(errp *error, format string, argv ...interface{}) { func Contextf(errp *error, format string, argv ...interface{}) {
if *errp == nil { if *errp == nil {
......
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