Last active
June 28, 2022 16:29
-
-
Save BenjamenMeyer/ef9926913dcc3b165da8f25a459442a9 to your computer and use it in GitHub Desktop.
golang error wrapping
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import ( | |
| "errors" | |
| "fmt" | |
| ) | |
| var ( | |
| Err1 error = errors.New("Err1") | |
| Err2 error = errors.New("Err2") | |
| Err3 error = errors.New("Err3") | |
| Err4 error = errors.New("Err4") | |
| ) | |
| func getSumErr() []error { | |
| return []error{ | |
| Err1, | |
| Err2, | |
| Err3, | |
| Err4, | |
| } | |
| } | |
| func checkForErrors(theErr error, allErrors []error) { | |
| fmt.Printf("Final error: %v\n", theErr) | |
| for _, ae := range allErrors { | |
| if errors.Is(theErr, ae) { | |
| fmt.Printf("Found %v\n", ae) | |
| } else { | |
| fmt.Printf("Did NOT find %v\n", ae) | |
| } | |
| } | |
| } | |
| func method1() { | |
| sumErrs := getSumErr() | |
| genErr := fmt.Errorf("My final error. verr: %w", sumErrs) | |
| checkForErrors(genErr, sumErrs) | |
| } | |
| func method2() { | |
| sumErrs := getSumErr() | |
| genErr := fmt.Errorf("My final error") | |
| for _, se := range sumErrs { | |
| genErr = fmt.Errorf("%v: %w", genErr, se) | |
| } | |
| checkForErrors(genErr, sumErrs) | |
| } | |
| func main() { | |
| fmt.Println("Method 1") | |
| method1() | |
| fmt.Println("Method 2") | |
| method2() | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Method 1 | |
| Final error: My final error. verr: %!w([]error=[0xc000010250 0xc000010260 0xc000010270 0xc000010280]) | |
| Did NOT find Err1 | |
| Did NOT find Err2 | |
| Did NOT find Err3 | |
| Did NOT find Err4 | |
| Method 2 | |
| Final error: My final error: Err1: Err2: Err3: Err4 | |
| Did NOT find Err1 | |
| Did NOT find Err2 | |
| Did NOT find Err3 | |
| Found Err4 | |
| Program exited. |
Author
Author
NOTE: Consider that the code receiving genErr doesn't know anything about the code that's generated Err1, Err2, and Err3 but the code generating Err4 noted their existing in its documentation. This could be for multiple reasons - Err2 could be a File not opened type error with Err3 and Err4 providing more details. The handler may or may not be able to do something about Err2 but it has to be able to detect it first. This promotes error re-use:
var ErrSomeErr error = errors.New("some error")
...
return fmt.Errorf("%w: some detail", ErrSomeErr)
...
return fmt.Errorf("%w: some more details", wrappedErrSomeErr)
...
return fmt.Errorf("%w: some other detail", wrappedWrappedErrSomeErr)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
NOTES:
getSumErr()as the errors built up throughout the code when an error is returnedgenErras sent tocheckForErrors()as the final error seen by the layer testing for an errorUnfortunately currently (Golang 1.18) can't detect that the earlier errors (Err1, Err2, Err3) are part of the error.
I even tried adding:
However, that pulls out
Err4:The other errors are not unwrapped. Perhaps proposals like golang/go#53435 can help solve that in future versions of Golang.