diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 6299192..b4b7f1f 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -35,5 +35,6 @@ ## API and Compatibility Notes - Do not introduce new usage of deprecated `Cause()`; prefer `errors.Is`/`errors.As` compatible flows and `Unwrap`/`Unwraps`. +- Keep `errs.Join` behavior stable: ignore nil arguments and return nil when all arguments are nil. - Treat changes to exported symbols, function signatures, and observable error formatting behavior as potentially breaking. - Error string and JSON formatting are validated by tests; when output behavior changes, update README examples and test expectations in the same change. diff --git a/README.md b/README.md index 6478d75..9340b46 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,7 @@ For multiple causes, it returns all causes as a slice. - `errs.New("")` returns `nil` - `errs.Wrap(nil)` returns `nil` - If `WithCause` is given multiple times, the last cause is used +- `errs.Join(...)` ignores `nil` arguments and returns `nil` if all arguments are `nil` ### Create new error instance with cause diff --git a/errlist.go b/errlist.go index 6cb1b19..d25b9a5 100644 --- a/errlist.go +++ b/errlist.go @@ -17,6 +17,8 @@ type Errors struct { } // Join function returns Errors instance. +// +// Join ignores nil elements in arguments and returns nil if all elements are nil. func Join(errlist ...error) error { if len(errlist) == 0 { return nil diff --git a/zapobject/example_test.go b/zapobject/example_test.go index 3209a3f..47ec4f8 100644 --- a/zapobject/example_test.go +++ b/zapobject/example_test.go @@ -10,7 +10,7 @@ import ( "go.uber.org/zap" ) -func checkFileOpen(path string) error { +func checkFileOpen(path string) (retErr error) { file, err := os.Open(path) if err != nil { return errs.New( @@ -19,7 +19,15 @@ func checkFileOpen(path string) error { errs.WithContext("path", path), ) } - defer file.Close() + defer func() { + if err := file.Close(); err != nil { + closeErr := errs.Wrap( + err, + errs.WithContext("path", path), + ) + retErr = errs.Join(retErr, closeErr) + } + }() return nil } @@ -41,7 +49,7 @@ func generateMultiError() error { func Example() { logger := zap.NewExample() - defer logger.Sync() + defer func() { _ = logger.Sync() }() if err := checkFileOpen("not-exist.txt"); err != nil { logger.Error("err", zap.Object("error", zapobject.New(err)))