github.com/Schaudge/grailbase@v0.0.0-20240223061707-44c758a471c0/errors/clean_up.go (about) 1 package errors 2 3 import ( 4 "context" 5 "fmt" 6 ) 7 8 // CleanUp is defer-able syntactic sugar that calls f and reports an error, if any, 9 // to *err. Pass the caller's named return error. Example usage: 10 // 11 // func processFile(filename string) (_ int, err error) { 12 // f, err := os.Open(filename) 13 // if err != nil { ... } 14 // defer errors.CleanUp(f.Close, &err) 15 // ... 16 // } 17 // 18 // If the caller returns with its own error, any error from cleanUp will be chained. 19 func CleanUp(cleanUp func() error, dst *error) { 20 addErr(cleanUp(), dst) 21 } 22 23 // CleanUpCtx is CleanUp for a context-ful cleanUp. 24 func CleanUpCtx(ctx context.Context, cleanUp func(context.Context) error, dst *error) { 25 addErr(cleanUp(ctx), dst) 26 } 27 28 func addErr(err2 error, dst *error) { 29 if err2 == nil { 30 return 31 } 32 if *dst == nil { 33 *dst = err2 34 return 35 } 36 // Note: We don't chain err2 as *dst's cause because *dst may already have a meaningful cause. 37 // Also, even if *dst didn't, err2 may be something entirely different, and suggesting it's 38 // the cause could be misleading. 39 // TODO: Consider using a standardized multiple-errors representation like sync/multierror's. 40 *dst = E(*dst, fmt.Sprintf("second error in Close: %v", err2)) 41 }