Good point Harri, This is what the correct version will look like using this proposal
func CopyFile(src, dst string) error { r, err := os.Open(src) *orelse* return fmt.Errorf("copy %s %s: %v", src, dst, err) defer r.Close() w, err := os.Create(dst); *orelse* return fmt.Errorf("copy %s %s: %v", src, dst, err) err := io.Copy(w, r) *orelse* { w.Close() os.Remove(dst) return fmt.Errorf("copy %s %s: %v", src, dst, err) } err := w.Close() *orelse* { os.Remove(dst) return fmt.Errorf("copy %s %s: %v", src, dst, err) } } In a more complex func, the error formatting/handling code can be further deduplicated by extracting it into a closure. e.g., func CopyFile(src, dst string) error { copyErr:= func(err error) { return fmt.Errorf("copy %s %s: %v", src, dst, err) } r, err := os.Open(src) *orelse* return copyErr(err) defer r.Close() w, err := os.Create(dst); *orelse* return copyErr(err) err := io.Copy(w, r) *orelse* { w.Close() os.Remove(dst) return copyErr(err) } err := w.Close() *orelse* { os.Remove(dst) return copyErr(err) } } On Sunday, July 30, 2023 at 8:17:31 AM UTC-6 Harri L wrote: > IMHO, you have used the irrelevant example (== 2nd code block) from Russ > Cox's paper. The paper says: > > This code is not nice, not clean, not elegant, *and still wrong:* like > the previous version, it does not remove dst when io.Copy or w.Close > fails. > > I want to compare your proposal with the third example from the paper, > which does (proper) error annotation and cleanup. Thanks. > On Sunday, July 30, 2023 at 8:57:15 AM UTC+3 DrGo wrote: > >> I looked at the long list of proposals to improve error handling in go >> but I have not seen the one I am describing below. If I missed a similar , >> can you pls direct me to where I can find it. If not what do you think of >> this approach. >> >> This involves introducing a new keyword "orelse" that is a syntactic >> sugar for an "if err!=nil" block. >> >> The example code in Russ Cox's paper[1] will look something like this: >> >> func CopyFile(src, dst string) error { >> >> r, err := os.Open(src) orelse return err >> >> defer r.Close() >> >> w, err := os.Create(dst) orelse return err >> >> defer w.Close() >> >> err = io.Copy(w, r) orelse return err >> >> err = w.Close() orelse return err >> >> } >> >> It is an error to not return an error from an orelse block. >> >> In my eyes, this has the same explicitness and flexibility of the current >> style but is significantly less verbose. It permits ignoring the error, >> returning it as is or wrapping it. Because orelse is not used for any other >> purpose, it would be easy for reviewers and linters to spot lack of error >> handling. >> >> It also works well with named returns. e.g., >> >> func returnsObjorErro() (obj Obj, err error) { >> >> obj, err := createObj() orelse return //returns nil and err >> >> } >> >> otherwise orelse is like "else" so e.g., it can be followed by a block if >> additional cleanup or error formatting etc is needed before returning, eg >> w, err := os.Create(dst) orelse { >> .... >> return err >> } >> >> Similarity to "else" hopefully means that it is easy to learn. It is >> obviously backward compatible >> >> What do you think? >> >> [1] >> https://go.googlesource.com/proposal/+/master/design/go2draft-error-handling-overview.md >> > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/db03dc82-6a11-4593-9f20-d8c5863c1e4an%40googlegroups.com.