Hey gophers, I would like to know your opinion on the following topic.
In my experience, the most popular case for
errors.Join is to handle deferred potential errors such as closing os.File, sql.Rows or http.Response.Body.
Might be a bit of a contrived example, it get the main point though:
```go
func WriteJSONTo(v any, filename string) (err error) {
file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0644)
if err != nil {
return err
}
defer func() { err = errors.Join(err, file.Close()) }()
return json.NewEncoder(file).Encode(v)
}
```
Although such deferred errors are still worth handling, I assume that they are unlikely to happen. That is, most function calls look like either `errors.Join(nil, nil)` or `errors.Join(someNonNilErr, nil)`
And the function itself always returns either nil or a wrapped trough `*errors.joinError` implementation, even if only one non-nil error is provided.
So, what do you think it makes sense for the function to return a wrapped error even if it contains only one error? Wouldn't it be more rational in such cases for Join to return that single error?
In addition, if such a use case occurs quite often, then avoiding unnecessary allocation could be a pleasant bonus:
```go
func BenchmarkJoinTwoErrors(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = Join(io.EOF, io.ErrNoProgress)
}
}
func BenchmarkJoinOneError(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = Join(io.EOF, nil)
}
}
```
```
goos: linux
goarch: amd64
pkg: fallout
cpu: 12th Gen Intel(R) Core(TM) i9-12900K
│ 1.txt │ 5.txt │
│ sec/op │ sec/op vs base │
JoinTwoErrors-24 20.87n ± 2% 21.18n ± 2% ~ (p=0.075 n=10)
JoinOneError-24 17.010n ± 2% 1.321n ± 1% -92.23% (p=0.000 n=10)
geomean 18.84n 5.290n -71.92%
│ 1.txt │ 5.txt │
│ B/op │ B/op vs base │
JoinTwoErrors-24 32.00 ± 0% 32.00 ± 0% ~ (p=1.000 n=10) ¹
JoinOneError-24 16.00 ± 0% 0.00 ± 0% -100.00% (p=0.000 n=10)
geomean 22.63 ? ² ³
¹ all samples are equal
² summaries must be >0 to compute geomean
³ ratios must be >0 to compute geomean
│ 1.txt │ 5.txt │
│ allocs/op │ allocs/op vs base │
JoinTwoErrors-24 1.000 ± 0% 1.000 ± 0% ~ (p=1.000 n=10) ¹
JoinOneError-24 1.000 ± 0% 0.000 ± 0% -100.00% (p=0.000 n=10)
geomean 1.000 ? ² ³
¹ all samples are equal
² summaries must be >0 to compute geomean
³ ratios must be >0 to compute geomean
```