adverr/README.md

159 lines
3.3 KiB
Markdown
Raw Normal View History

2020-09-09 13:34:23 +02:00
# adverr
Package adverr implements errors with call stack traces
as well as error templates for error equality
## Installation
```
go get git.tordarus.net/tordarus/adverr
```
## Usage examples
2020-09-09 14:07:55 +02:00
### Import
2020-09-09 13:34:23 +02:00
```go
import "git.tordarus.net/tordarus/adverr"
```
2020-09-09 14:07:55 +02:00
### Create error templates
2020-09-09 13:34:23 +02:00
```go
var (
ErrDoStuffFailed = adverr.NewErrTmpl("ErrDoStuffFailed", "Could'nt do stuff because of %s")
)
```
2020-09-09 14:07:55 +02:00
### Create independent error (without error template)
2020-09-09 13:34:23 +02:00
```go
func doStuffWithIndependentErr() error {
return adverr.New("Could'nt do stuff")
}
```
2020-09-09 14:07:55 +02:00
### Create error based on template
2020-09-09 13:34:23 +02:00
```go
func doStuff() error {
return ErrDoStuffFailed.New("reasons")
}
```
2020-09-09 14:07:55 +02:00
### Print errors on stderr convieniently
2020-09-09 13:34:23 +02:00
```go
adverr.Print(myErr)
adverr.Println(myErr)
```
2020-09-09 14:07:55 +02:00
### Print errors on stderr and exit with exit code
2020-09-09 13:34:23 +02:00
```go
adverr.Fatal(myErr, 1)
adverr.Fatalln(myErr, 1)
```
### Advantages of error templates
two errors made by the same template will return true when called with `errors.Is()`
```go
func doStuffAndFailWithMsg(msg string) error {
return ErrDoStuffFailed.New(msg)
}
err1 := doStuffAndFailWithMsg("err1")
err2 := doStuffAndFailWithMsg("err2")
fmt.Println(errors.Is(err1, err2)) // true
fmt.Println(err1 == err2) // false
fmt.Println(err1.Error() == err2.Error()) // false
```
2020-09-09 14:07:55 +02:00
### Wrap errors (Causality of errors)
2020-09-09 13:34:23 +02:00
By wrapping errors, you can provide an error that is caused by another error.
A 'Caused by' section will be printed in the stack trace showing the original error.
You can also retrieve the original error by using `errors.Unwrap()`
```go
func doStuffWrapped() error {
err := doStuff()
if err != nil {
return adverr.Wrap("doStuffWrapped failed", err)
}
return nil
}
```
2020-09-09 14:07:55 +02:00
### Retrieve call stack trace (for debugging purposes)
2020-09-09 13:34:23 +02:00
```go
fmt.Println(adverr.Trace())
```
2020-09-09 14:06:31 +02:00
### Example of a printed error
Code:
```go
package main
import (
"adverr"
"errors"
)
var (
ErrDoStuffFailed = adverr.NewErrTmpl("ErrDoStuffFailed", "Could'nt do stuff because of %s")
)
func main() {
err := doStuffInAnotherGoroutine()
if err != nil {
adverr.Fatalln(err, 1)
}
}
func doStuff() error {
err := doGoNativeStuff()
if err != nil {
return ErrDoStuffFailed.Wrap(err, "reasons")
}
return nil
}
func doStuffInAnotherGoroutine() error {
ch := make(chan error, 1)
go func() {
ch <- doStuff()
close(ch)
}()
err := <-ch
if err != nil {
return adverr.Wrap("Goroutine failed because of errors", err)
}
return nil
}
func doGoNativeStuff() error {
return errors.New("some go error")
}
```
Output:
```
adverr.Error: Goroutine failed because of errors
at main.doStuffInAnotherGoroutine (/home/user/go/src/test/main.go:38)
at main.main (/home/user/go/src/test/main.go:13)
at runtime.main (/usr/local/go/src/runtime/proc.go:204)
Caused by ErrDoStuffFailed: Could'nt do stuff because of reasons
at main.doStuff (/home/user/go/src/test/main.go:22)
at main.doStuffInAnotherGoroutine.func1 (/home/user/go/src/test/main.go:32)
Caused by errors.errorString: some go error
(Unknown source)
```
### Globals
You can set the maximum limit of the call stack trace via
```go
adverr.CallStackLength = 50 // default value: 100
```
If you are in a productive environment, consider disabling call traces completely for performance reasons:
```go
adverr.DisableTrace = true // default value: false
```