|
|
@@ -53,28 +53,40 @@ func (e Error) Unwrap() []error {
|
|
|
// If the resulting slice has length 1, New returns that error.
|
|
|
// If the resulting slice has length > 1, New returns that slice as an Error.
|
|
|
func New(errs ...error) error {
|
|
|
- dst := make([]error, 0, len(errs))
|
|
|
+ // First count the number of errors to avoid allocating.
|
|
|
+ var n int
|
|
|
+ var errFirst error
|
|
|
for _, e := range errs {
|
|
|
switch e := e.(type) {
|
|
|
case nil:
|
|
|
continue
|
|
|
case Error:
|
|
|
- dst = append(dst, e.errs...)
|
|
|
+ n += len(e.errs)
|
|
|
+ if errFirst == nil && len(e.errs) > 0 {
|
|
|
+ errFirst = e.errs[0]
|
|
|
+ }
|
|
|
default:
|
|
|
- dst = append(dst, e)
|
|
|
+ n++
|
|
|
+ if errFirst == nil {
|
|
|
+ errFirst = e
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
- // dst has been filtered and splatted.
|
|
|
- switch len(dst) {
|
|
|
- case 0:
|
|
|
- return nil
|
|
|
- case 1:
|
|
|
- return dst[0]
|
|
|
+ if n <= 1 {
|
|
|
+ return errFirst // nil if n == 0
|
|
|
}
|
|
|
- // Zero any remaining elements of dst left over from errs, for GC.
|
|
|
- tail := dst[len(dst):cap(dst)]
|
|
|
- for i := range tail {
|
|
|
- tail[i] = nil
|
|
|
+
|
|
|
+ // More than one error, allocate slice and construct the multi-error.
|
|
|
+ dst := make([]error, 0, n)
|
|
|
+ for _, e := range errs {
|
|
|
+ switch e := e.(type) {
|
|
|
+ case nil:
|
|
|
+ continue
|
|
|
+ case Error:
|
|
|
+ dst = append(dst, e.errs...)
|
|
|
+ default:
|
|
|
+ dst = append(dst, e)
|
|
|
+ }
|
|
|
}
|
|
|
return Error{errs: dst}
|
|
|
}
|