...
1
2 package errors
3
4 import (
5 "fmt"
6 "runtime"
7 "strings"
8 )
9
10
11
12
13 type ContextualError struct {
14 Err error
15 Context string
16 Message string
17 }
18
19
20
21
22
23
24
25
26
27
28
29 func New(msg string, e error) *ContextualError {
30 err := &ContextualError{Message: msg, Err: e}
31
32
33 pc, file, line, ok := runtime.Caller(1)
34 details := runtime.FuncForPC(pc)
35
36 if ok && details != nil {
37 name := details.Name()
38
39 err.Context = fmt.Sprintf("%s:%s#%d", name, file, line)
40 }
41 return err
42 }
43
44
45 func (c *ContextualError) Error() string {
46 if c.Message == "" {
47 c.Message = "failed."
48 }
49
50 str := c.Message
51
52 if !(strings.HasSuffix(c.Message, ".") ||
53 strings.HasSuffix(c.Message, "!") ||
54 strings.HasSuffix(c.Message, "?")) {
55 str = fmt.Sprintf("%s.", str)
56 }
57
58
59 if c.Err != nil {
60 str = fmt.Sprintf("%s error: %v", str, c.Err)
61 }
62
63
64 if c.Context != "" {
65 str = fmt.Sprintf("%s: %s", c.Context, str)
66 }
67
68 return str
69 }
70
71 func (c *ContextualError) Unwrap() error { return c.Err }
72
73
74 func Wrap(e error) *ContextualError {
75 return New("", e)
76 }
77
View as plain text