-
Notifications
You must be signed in to change notification settings - Fork 0
/
errors.go
125 lines (114 loc) · 3.23 KB
/
errors.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// Package errors provides Pure Golang errors library with stacktrace support (for wrapping, formatting and joining an errors).
//
// Add errors context to your report just by wrapping it with stacktrace.
//
// b, err := json.Unmarshal(data, &Data)
// if err != nil {
// return errors.WithStack(err)
// }
//
// Describe more error details by wrapping it with message.
//
// data := "foo"
// if err := Do("foo"); err != nil {
// return errors.Wrapf(err, "failed to do %q", data)
// }
//
// Debugging will be easier when you can see the stacktrace.
//
// if err := HugeStackCall(ctx); err != nil {
// fmt.Printf("[ERROR]: %+v", err)
// }
package errors
import (
"fmt"
"io"
errors "github.com/Cleverse/go-utilities/errors/errconstructor"
)
// New returns an error with the supplied message.
// New also records the stack trace at the point it was called.
//
// this function is supports to skip stack frames. default is 0 (begin at your current function call)
// for more information see WithStack function in github.com/Cleverse/go-utilities/errors/errconstructor
func New(text string, skip ...int) error {
skipNum := 0
if len(skip) > 0 {
skipNum = skip[0]
}
return &stdError{
s: text,
stack: errors.Callers(skipNum),
}
}
// Errorf formats according to a format specifier and returns the string
// as a value that satisfies error.
// Errorf also records the stack trace at the point it was called.
func Errorf(format string, args ...interface{}) error {
return &stdError{
s: fmt.Sprintf(format, args...),
stack: errors.Callers(0),
}
}
// stdError is an standard error that contains a message and a stack trace.
type stdError struct {
stack *errors.Stacks
s string
}
func (f *stdError) Error() string {
return f.s
}
func (f *stdError) Format(s fmt.State, verb rune) {
switch verb {
case 'v':
if s.Flag('+') {
_, _ = io.WriteString(s, f.s)
f.stack.Format(s, verb)
return
}
fallthrough
case 's':
_, _ = io.WriteString(s, f.s)
case 'q':
fmt.Fprintf(s, "%q", f.s)
}
}
// WithStack annotates err with a stack trace at the point WithStack was called.
// If err is nil, WithStack returns nil.
func WithStack(err error) error {
return errors.WithStack(err, 1)
}
// Wrap returns an error annotating err with a stack trace
// at the point Wrap is called, and the supplied message.
// If err is nil, Wrap returns nil.
func Wrap(err error, message string) error {
return errors.Wrap(err, 1, message)
}
// Wrapf returns an error annotating err with a stack trace
// at the point Wrapf is called, and the format specifier.
// If err is nil, Wrapf returns nil.
func Wrapf(err error, format string, args ...interface{}) error {
return errors.Wrapf(err, 1, format, args...)
}
// Cause returns the underlying cause of the error, if possible.
// An error value has a cause if it implements the following
// interface:
//
// type causer interface {
// Cause() error
// }
//
// If the error does not implement Cause, the original error will
// be returned. If the error is nil, nil will be returned without further
// investigation.
//
// nolint: errorlint, wrapcheck
func Cause(err error) error {
for err != nil {
cause, ok := err.(interface{ Cause() error })
if !ok {
break
}
err = cause.Cause()
}
return err
}