...
1
2
3
4 package multierror
5
6 import (
7 "fmt"
8 "strings"
9 )
10
11 const Prefix = "- "
12 const Indent = " "
13
14 type Interface interface {
15 Errors() []error
16 }
17
18
19 func New(causes ...error) *MultiError {
20 return &MultiError{
21 Causes: causes,
22 }
23 }
24
25
26 type MultiError struct {
27 Causes []error
28 }
29
30 func (mve *MultiError) Errors() []error {
31 return mve.Causes
32 }
33
34 func (mve *MultiError) Error() string {
35 if len(mve.Causes) == 1 {
36 return mve.Causes[0].Error()
37 }
38 var b strings.Builder
39 _, _ = fmt.Fprintf(&b, "%d errors:\n", len(mve.Causes))
40 for _, err := range mve.Causes {
41 _, _ = fmt.Fprintf(&b, "%s\n", formatError(err))
42 }
43 return b.String()
44 }
45
46 func formatError(err error) string {
47 lines := strings.Split(err.Error(), "\n")
48 return Prefix + strings.Join(lines, fmt.Sprintf("\n%s", Indent))
49 }
50
51
52
53
54 func Wrap(errs ...error) error {
55 if len(errs) == 0 {
56 return nil
57 }
58 errs = Unwrap(errs...)
59 var err error
60 switch {
61 case len(errs) == 0:
62 err = nil
63 case len(errs) == 1:
64 err = errs[0]
65 case len(errs) > 1:
66 err = &MultiError{
67 Causes: errs,
68 }
69 }
70 return err
71 }
72
73
74
75 func Unwrap(errs ...error) []error {
76 if len(errs) == 0 {
77 return nil
78 }
79 var errors []error
80 for _, err := range errs {
81 if mve, ok := err.(Interface); ok {
82
83 for _, cause := range mve.Errors() {
84 errors = append(errors, Unwrap(cause)...)
85 }
86 } else {
87 errors = append(errors, err)
88 }
89 }
90 return errors
91 }
92
View as plain text