@@ -3,7 +3,6 @@ package syncs
3
3
import (
4
4
"context"
5
5
"fmt"
6
- "strings"
7
6
"sync"
8
7
)
9
8
@@ -64,7 +63,7 @@ func NewErrSizedGroup(size int, options ...GroupOption) *ErrSizedGroup {
64
63
// The first call to return a non-nil error cancels the group if termOnError; its error will be
65
64
// returned by Wait. If no termOnError all errors will be collected in multierror.
66
65
func (g * ErrSizedGroup ) Go (f func (ctx context.Context ) error ) {
67
- if g .canceled () && (! g .termOnError || len ( g .err .Errors () ) == 0 ) {
66
+ if g .canceled () && (! g .termOnError || g .err .len ( ) == 0 ) {
68
67
g .errOnce .Do (func () {
69
68
// don't repeat this error
70
69
g .err .append (g .ctx .Err ())
@@ -120,51 +119,57 @@ func (g *ErrSizedGroup) Go(f func(ctx context.Context) error) {
120
119
// returns all errors (if any) wrapped with multierror from them.
121
120
func (g * ErrSizedGroup ) Wait () error {
122
121
g .wg .Wait ()
122
+ g .err .makeStr ()
123
123
return g .err .ErrorOrNil ()
124
124
}
125
125
126
126
// MultiError is a thread safe container for multi-error type that implements error interface
127
127
type MultiError struct {
128
128
errors []error
129
- lock sync.Mutex
130
- }
131
-
132
- func (m * MultiError ) append (err error ) * MultiError {
133
- m .lock .Lock ()
134
- m .errors = append (m .errors , err )
135
- m .lock .Unlock ()
136
- return m
129
+ lock sync.RWMutex
130
+ str string
137
131
}
138
132
139
133
// ErrorOrNil returns nil if no errors or multierror if errors occurred
140
134
func (m * MultiError ) ErrorOrNil () error {
141
- m .lock .Lock ()
142
- defer m .lock .Unlock ()
143
- if len (m .errors ) == 0 {
135
+ if m .len () == 0 {
144
136
return nil
145
137
}
146
138
return m
147
139
}
148
140
149
141
// Error returns multi-error string
150
142
func (m * MultiError ) Error () string {
151
- m .lock .Lock ()
152
- defer m .lock .Unlock ()
153
- if len (m .errors ) == 0 {
154
- return ""
155
- }
156
-
157
- errs := []string {}
158
-
159
- for n , e := range m .errors {
160
- errs = append (errs , fmt .Sprintf ("[%d] {%s}" , n , e .Error ()))
161
- }
162
- return fmt .Sprintf ("%d error(s) occurred: %s" , len (m .errors ), strings .Join (errs , ", " ))
143
+ return m .str
163
144
}
164
145
165
146
// Errors returns all errors collected
166
147
func (m * MultiError ) Errors () []error {
167
- m .lock .Lock ()
168
- defer m .lock .Unlock ()
169
148
return m .errors
170
149
}
150
+
151
+ func (m * MultiError ) append (err error ) {
152
+ m .lock .Lock ()
153
+ m .errors = append (m .errors , err )
154
+ m .lock .Unlock ()
155
+ }
156
+
157
+ func (m * MultiError ) len () int {
158
+ m .lock .RLock ()
159
+ defer m .lock .RUnlock ()
160
+ return len (m .errors )
161
+ }
162
+
163
+ func (m * MultiError ) makeStr () {
164
+ lenErrors := m .len ()
165
+ if lenErrors == 0 {
166
+ return
167
+ }
168
+ errs := fmt .Sprintf ("[0] {%s}" , m .Errors ()[0 ].Error ())
169
+ if lenErrors > 1 {
170
+ for n , e := range m .Errors ()[1 :] {
171
+ errs += fmt .Sprintf (", [%d] {%s}" , n + 1 , e .Error ())
172
+ }
173
+ }
174
+ m .str = fmt .Sprintf ("%d error(s) occurred: %s" , lenErrors , errs )
175
+ }
0 commit comments