Avoid allocating a new slice on every Append (#9)

Currently, appending a non-nil error to a multierror always copies the underlying slice, since there may be multiple goroutines appending to the same multierr,
```go
merr := multierr.Append(errors.New("initial"), errors.New("multierr"))
go func() {
  err1 = multierr.Append(merr, errors.New("1"))
  [..]
}()
go func() {
  err2 = multierr.Append(merr, errors.New("2"))
  [..]
}()
```

However, the common use case is a standard for loop:
```go
var merr error
for _, v := range values {
  merr = multierr.Append(merr, processValue(v))
}
return merr
```

Since there is only a single resulting slice, we don't need to create a full copy on every `Append`. Instead, we track whether we have modified the underlying slice from `Append` already using an atomic boolean, and only create a copy if the underlying slice has been modified.

4 files changed
tree: f96f2d5d78b4a5b75f5b153f5d1b29692064462c
  1. scripts/
  2. .gitignore
  3. .travis.yml
  4. benchmarks_test.go
  5. CHANGELOG.md
  6. error.go
  7. error_test.go
  8. glide.lock
  9. glide.yaml
  10. LICENSE.txt
  11. Makefile
  12. README.md
README.md

multierr GoDoc Build Status Coverage Status

multierr allows combining one or more Go errors together.

Installation

go get -u go.uber.org/multierr

Status

Beta


Released under the MIT License.