From ecbd1b284f2ad7f6a1e174726824f7fa892479f2 Mon Sep 17 00:00:00 2001 From: Spiegel Date: Mon, 26 Jun 2023 19:39:16 +0900 Subject: [PATCH 1/2] Update README.md --- README.md | 27 +++++++++++++++++++++++---- sample/sample5.go | 18 +++--------------- sample/sample6.go | 31 +++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 19 deletions(-) create mode 100644 sample/sample6.go diff --git a/README.md b/README.md index 2e9f3b0..16432e8 100644 --- a/README.md +++ b/README.md @@ -142,7 +142,7 @@ func main() { } ``` -### Wrapping multiple errors instance +### Handling multiple errors ```go package main @@ -151,6 +151,27 @@ import ( "errors" "fmt" "io" + "os" + + "github.com/goark/errs" +) + +func generateMultiError() error { + return errs.Join(os.ErrInvalid, io.EOF) +} + +func main() { + err := generateMultiError() + fmt.Printf("%+v\n", err) // {"Type":"*errs.Errors","Errs":[{"Type":"*errors.errorString","Msg":"invalid argument"},{"Type":"*errors.errorString","Msg":"EOF"}]} + fmt.Println(errors.Is(err, io.EOF)) // true +} +``` + +```go +package main + +import ( + "fmt" "sync" "github.com/goark/errs" @@ -168,14 +189,12 @@ func generateMultiError() error { }() } wg.Wait() - errlist.Add(io.EOF) return errlist.ErrorOrNil() } func main() { err := generateMultiError() - fmt.Printf("%+v\n", err) // {"Type":"*errs.Errors","Errs":[{"Type":"*errors.errorString","Msg":"error 2"},{"Type":"*errors.errorString","Msg":"error 1"},{"Type":"*errors.errorString","Msg":"EOF"}]} - fmt.Println(errors.Is(err, io.EOF)) // true + fmt.Printf("%+v\n", err) // {"Type":"*errs.Errors","Errs":[{"Type":"*errors.errorString","Msg":"error 2"},{"Type":"*errors.errorString","Msg":"error 1"}]} } ``` diff --git a/sample/sample5.go b/sample/sample5.go index 9c8babd..40bb68a 100644 --- a/sample/sample5.go +++ b/sample/sample5.go @@ -7,29 +7,17 @@ import ( "errors" "fmt" "io" - "sync" + "os" "github.com/goark/errs" ) func generateMultiError() error { - errlist := &errs.Errors{} - var wg sync.WaitGroup - for i := 1; i <= 2; i++ { - i := i - wg.Add(1) - go func() { - defer wg.Done() - errlist.Add(fmt.Errorf("error %d", i)) - }() - } - wg.Wait() - errlist.Add(io.EOF) - return errlist.ErrorOrNil() + return errs.Join(os.ErrInvalid, io.EOF) } func main() { err := generateMultiError() - fmt.Printf("%+v\n", err) // {"Type":"*errs.Errors","Errs":[{"Type":"*errors.errorString","Msg":"error 2"},{"Type":"*errors.errorString","Msg":"error 1"},{"Type":"*errors.errorString","Msg":"EOF"}]} + fmt.Printf("%+v\n", err) // {"Type":"*errs.Errors","Errs":[{"Type":"*errors.errorString","Msg":"invalid argument"},{"Type":"*errors.errorString","Msg":"EOF"}]} fmt.Println(errors.Is(err, io.EOF)) // true } diff --git a/sample/sample6.go b/sample/sample6.go new file mode 100644 index 0000000..6cf2e25 --- /dev/null +++ b/sample/sample6.go @@ -0,0 +1,31 @@ +//go:build run +// +build run + +package main + +import ( + "fmt" + "sync" + + "github.com/goark/errs" +) + +func generateMultiError() error { + errlist := &errs.Errors{} + var wg sync.WaitGroup + for i := 1; i <= 2; i++ { + i := i + wg.Add(1) + go func() { + defer wg.Done() + errlist.Add(fmt.Errorf("error %d", i)) + }() + } + wg.Wait() + return errlist.ErrorOrNil() +} + +func main() { + err := generateMultiError() + fmt.Printf("%+v\n", err) // {"Type":"*errs.Errors","Errs":[{"Type":"*errors.errorString","Msg":"error 2"},{"Type":"*errors.errorString","Msg":"error 1"}]} +} From 2a5157c63e5a001ad684b1b5c63b8e4f1a4040b6 Mon Sep 17 00:00:00 2001 From: Spiegel Date: Mon, 26 Jun 2023 20:22:31 +0900 Subject: [PATCH 2/2] Fixed the Errors.Unwrap method to return a copy of the slice --- errlist.go | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/errlist.go b/errlist.go index 18137d5..dc1069d 100644 --- a/errlist.go +++ b/errlist.go @@ -13,7 +13,7 @@ import ( // Errors is multiple error instance. type Errors struct { mu sync.RWMutex - Errs []error + errs []error } // Join function returns Errors instance. @@ -30,10 +30,10 @@ func Join(errlist ...error) error { if ct == 0 { return nil } - es := &Errors{Errs: make([]error, 0, ct)} + es := &Errors{errs: make([]error, 0, ct)} for _, err := range errlist { if err != nil { - es.Errs = append(es.Errs, err) + es.errs = append(es.errs, err) } } return es @@ -48,7 +48,7 @@ func (es *Errors) Add(errlist ...error) { defer es.mu.Unlock() for _, err := range errlist { if err != nil { - es.Errs = append(es.Errs, err) + es.errs = append(es.errs, err) } } } @@ -60,7 +60,7 @@ func (es *Errors) ErrorOrNil() error { } es.mu.RLock() defer es.mu.RUnlock() - if len(es.Errs) == 0 { + if len(es.errs) == 0 { return nil } return es @@ -74,11 +74,11 @@ func (es *Errors) Error() string { } es.mu.RLock() defer es.mu.RUnlock() - if len(es.Errs) == 0 { + if len(es.errs) == 0 { return nilAngleString } var b []byte - for i, err := range es.Errs { + for i, err := range es.errs { if i > 0 { b = append(b, '\n') } @@ -101,10 +101,10 @@ func (es *Errors) GoString() string { } es.mu.RLock() defer es.mu.RUnlock() - if len(es.Errs) == 0 { + if len(es.errs) == 0 { return nilAngleString } - return fmt.Sprintf("%T{Errs:%#v}", es, es.Errs) + return fmt.Sprintf("%T{Errs:%#v}", es, es.errs) } // MarshalJSON method returns serialize string of Errors with JSON format. @@ -142,9 +142,9 @@ func (es *Errors) EncodeJSON() string { defer es.mu.RUnlock() elms := []string{} elms = append(elms, strings.Join([]string{`"Type":`, strconv.Quote(reflect.TypeOf(es).String())}, "")) - if len(es.Errs) > 0 { + if len(es.errs) > 0 { elms2 := []string{} - for _, err := range es.Errs { + for _, err := range es.errs { msgBuf := &bytes.Buffer{} json.HTMLEscape(msgBuf, []byte(EncodeJSON(err))) elms2 = append(elms2, msgBuf.String()) @@ -162,10 +162,12 @@ func (es *Errors) Unwrap() []error { } es.mu.RLock() defer es.mu.RUnlock() - if len(es.Errs) == 0 { + if len(es.errs) == 0 { return nil } - return es.Errs + cpy := make([]error, len(es.errs), cap(es.errs)) + copy(cpy, es.errs) + return cpy } /* Copyright 2023 Spiegel