It is not just resistance to change, it is about not adding new features that add more complexity than value. I am pretty sure people will complain about Go's error handling even if we use "orelse return err".
Generics add a lot of value, it shows the Go team is open to changes. But imagine they add any feature people ask, C++ would be simpler than Go. As I said, I like the proposal, but I have learned that some times, I have to accept things are not always as I want them to be. On Fri, Aug 4, 2023, 08:58 Victor Giordano <vitucho3...@gmail.com> wrote: > As far as I see things there is always room for changes... but changes > doesn't come without some resistance.. That is natural... > > > Go best features is the lack of new features. > > What about generics? That was a major change... It was really necessary or > not is another topic. > > El vie, 4 ago 2023 a las 9:47, Miguel Angel Rivera Notararigo (< > ntr...@gmail.com>) escribió: > >> >> >> On Thu, Aug 3, 2023, 23:45 DrGo <salah.mah...@gmail.com> wrote: >> >>> @Miguel Angel Rivera Notararigo >>> >>> Thanks for taking the time to write... >>> >>> In my proposal, people are free to add as much context as they want... >>> >> >> Yeah I know, I like your proposal, it is just how they handle errors in >> the V programming language, although they use the keyword "or" and have >> Options/Results. >> >> but as a demonstration, I am using the example from >>> Ross Cox's paper on error handling that is used by all error handling >>> proposals to show case their approach. I do not think Ross will >>> take your criticism personally :) >>> >> >> I know, but just because he wrote that, doesn't mean it is the perfect >> example. If I find myself writing code like that, I would probably hate >> Go's error handling too, but that might be said for any other feature of >> the language if I write some bad looking examples. >> >> I don't see how he could take my opinion personally, I didn't mean to be >> rude, I just said it is a bad example. I am not a native speaker, so my >> apologies if I wrote something rude. >> >> I on the other hand take exception to your generalization re people who >>> complain about error handling in Go. >>> I am sure you did not make that claim without having some sort of solid >>> research to support it. But, Go designers themselves admit that this is an >>> issue and have written >>> tons on it. >>> >> >> You don't need a research or statistics if the complain is: "I don't want >> to write 'if err != nil { return err }' every single time". >> >> It means they use "if err := w.Close(); err != nil { return err }" for >> throwing the error, right? It is literally what they said or am I assuming? >> >> This same people will complain about your proposal, "I don't want to >> write 'orelse return err' every single time", and then we will add >> 'w.Close()!' or 'try w.Close()' to the language, and then we will be very >> happy with our Go++ wich has 3 ways of doing the same thing. >> >> >>> In one or two replies above we were discussing how error handling >>> opinions can become religions each with its own priests who think they are >>> the only saved faction, and that their rituals are the only right approach >>> for all situations. >>> >> >> I know, as I said, I like your proposal, but one of Go best features is >> the lack of new features. I am arguing against my own taste, because I like >> 'w.Close() or return fmt.Errorf("cannot close destination: %v", err)', but >> I like more the simplicity of Go. >> >> >>> Best wishes, >>> >>> >>> On Thursday, August 3, 2023 at 9:07:52 PM UTC-6 Miguel Angel Rivera >>> Notararigo wrote: >>> >>> func CopyFile(src, dst string) error { >>> r, err := os.Open(src) >>> if err != nil { >>> return fmt.Errorf("copy %s %s: %v", src, dst, err) >>> } >>> defer r.Close() >>> >>> w, err := os.Create(dst) >>> if err != nil { >>> return fmt.Errorf("copy %s %s: %v", src, dst, err) >>> } >>> >>> if _, err := io.Copy(w, r); err != nil { >>> w.Close() >>> os.Remove(dst) >>> return fmt.Errorf("copy %s %s: %v", src, dst, err) >>> } >>> >>> if err := w.Close(); err != nil { >>> os.Remove(dst) >>> return fmt.Errorf("copy %s %s: %v", src, dst, err) >>> } >>> } >>> >>> I think it is a bad example, how do you know where CopyFile failed? >>> >>> The "copy ..." part shouldn't be in there, you should add valuable >>> context to your errors, if CopyFile fails, the caller already knows it was >>> a copy error because the function has a big "Copy" on his name right? you >>> should do this instead: >>> >>> func CopyFile(dst, src string) error { >>> r, errOS := os.Open(src) // Avoid shadowing errors, don't use err >>> if errOS != nil { >>> return fmt.Errorf("cannot open source: %v", errOS) >>> } >>> >>> defer r.Close() >>> >>> w, errCD := os.Create(dst) >>> if errCD != nil { >>> return fmt.Errorf("cannot create destination: %v", errCD) >>> } >>> >>> defer w.Close() >>> >>> if _, err := io.Copy(w, r); err != nil { // Local scope error, so err >>> is fine >>> os.Remove(dst) >>> return fmt.Errorf("cannot copy data from source: %v", err) >>> >>> } >>> >>> if err := w.Close(); err != nil { >>> os.Remove(dst) >>> return fmt.Errorf("cannot close destination", err) >>> } >>> } >>> >>> // Caller should do this. >>> if err := CopyFile("dst.txt", "src.txt"); err != nil { >>> // Here is where you should add 'copy' to the error message. >>> return fmt.Errorf("cannot copy '%s' to '%s': %v", src, dst, err) >>> } >>> >>> People complaining about Go's error handling regularly don't handle >>> errors, they just throw them like exceptions. >>> >>> If you really hate Go's error handling, just use: >>> >>> func catch(err error) { >>> if err != nil { >>> panic(err) >>> } >>> >>> // And use recover somewhere >>> } >>> >>> Which is a bad practice, but at least we (the people who like how Go >>> handle errors) can still handle our errors without any language change. >>> >>> On Tue, Aug 1, 2023, 13:06 DrGo wrote: >>> >>> Thanks. >>> The keystroke saving is not the motivation. The aim is to reduce the >>> code reader’s mental load. My approach allows for clearer code where the >>> main program logic is not dwarfed by the error handling code while >>> maintaining the explicitly of error handling and the possible error-induced >>> interruption in program flow. It avoids creating new if scope when one is >>> not desired and offers opportunities for further deduplication of error >>> handling code although each error is still handled individually. Compare >>> the following; which one would you prefer to read a lot of? >>> >>> - current approach; error handling to program logic ratio: 13:5 >>> >>> func CopyFile(src, dst string) error { >>> r, err := os.Open(src) >>> if err != nil { >>> return fmt.Errorf("copy %s %s: %v", src, dst, err) >>> } >>> defer r.Close() >>> >>> w, err := os.Create(dst) >>> if err != nil { >>> return fmt.Errorf("copy %s %s: %v", src, dst, err) >>> } >>> >>> if _, err := io.Copy(w, r); err != nil { >>> w.Close() >>> os.Remove(dst) >>> return fmt.Errorf("copy %s %s: %v", src, dst, err) >>> } >>> >>> if err := w.Close(); err != nil { >>> os.Remove(dst) >>> return fmt.Errorf("copy %s %s: %v", src, dst, err) >>> } >>> } >>> >>> - new approach ratio 5:5 >>> 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) >>> } >>> } >>> >>> On Sunday, July 30, 2023 at 9:27:27 PM UTC-6 Marcello H wrote: >>> >>> I think the current error handling is just fine. >>> For the extra typing, they invented keyboard snippets and such. >>> >>> But for this proposal, I would like to see how a return with multiple >>> values would look to get a better understanding. >>> ``` >>> // translate this in the proposed solution? >>> func myFirstFunction() (string, err) { >>> result, err := myFunction() >>> if err != nill { >>> return rest, err >>> } >>> } >>> ``` >>> >>> Op maandag 31 juli 2023 om 04:32:01 UTC+2 schreef DrGo: >>> >>> Another possibility Jeremy is that the orelse block is executed if any >>> of the returned error values is not nil. >>> >>> On Sunday, July 30, 2023 at 8:14:58 PM UTC-6 DrGo wrote: >>> >>> Thanks... >>> yes indeed. Too many requirements but I think this solution comes close >>> to meeting them. If a rare function returns more than one error value (yet >>> to see one in the wild) then the compiler should reject orelse use and the >>> user can fallback on the (the if err!= nil) approach. >>> >>> On Sunday, July 30, 2023 at 6:02:57 PM UTC-6 Jeremy French wrote: >>> >>> Also, errors are values, which means - although uncommon - a function >>> could return two or more error values. Which would orelse evaluate? Even >>> if you arbitrarily chose one, that would violate the explicit vs implicit >>> code flow principle. >>> >>> My sympathies, OP. I too hate the "if err!= nil" boilerplate, and have >>> suggested my own idea for fixing it, which was similarly dismantled for >>> good reasons by those more knowledgeable than me. The truth is, this >>> problem/issue has so many restrictions placed on it (currently idiomatic >>> principles, backwards compatibility promise, explicit vs implicit, etc) >>> that the set of possible solutions is VERY narrow, possibly infinitely so. >>> >>> On Sunday, July 30, 2023 at 3:51:49 PM UTC-4 Brian Candler wrote: >>> >>> err := io.Copy(w, r) *orelse* { >>> w.Close() >>> os.Remove(dst) >>> return fmt.Errorf("copy %s %s: %v", src, dst, err) >>> } >>> >>> My question still stands. Semantically, what value exactly does the >>> "orelse" condition test is not equal to nil? >>> >>> - does it test the value from the preceding assignment? If so, is >>> "orelse" only valid immediately following an assignment expression? The >>> original posting didn't say this. And if it *is* linked to an assignment >>> expression which assigns multiple values, does it only look at the last >>> value? (Again, that was not specified) >>> >>> - does it always test a variable called "err"? The original posting said >>> it was equivalent to "if err!=nil" but a later post contradicted this >>> >>> - does it test the value from the 'return' expression at the end of the >>> block following orelse? Except in this case, it can't because it's buried >>> inside fmt.Errorf >>> >>> On Sunday, 30 July 2023 at 17:55:34 UTC+1 DrGo wrote: >>> >>> 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...@googlegroups.com. >>> To view this discussion on the web visit >>> https://groups.google.com/d/msgid/golang-nuts/36110a8d-a26f-48be-83fd-73af755e88f4n%40googlegroups.com >>> <https://groups.google.com/d/msgid/golang-nuts/36110a8d-a26f-48be-83fd-73af755e88f4n%40googlegroups.com?utm_medium=email&utm_source=footer> >>> . >>> >>> -- >>> 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/2c9fa4b1-e536-4743-ac20-181e550bd14fn%40googlegroups.com >>> <https://groups.google.com/d/msgid/golang-nuts/2c9fa4b1-e536-4743-ac20-181e550bd14fn%40googlegroups.com?utm_medium=email&utm_source=footer> >>> . >>> >> -- >> You received this message because you are subscribed to a topic in the >> Google Groups "golang-nuts" group. >> To unsubscribe from this topic, visit >> https://groups.google.com/d/topic/golang-nuts/dRLR4hxxI8A/unsubscribe. >> To unsubscribe from this group and all its topics, 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/CAF9DLCkTKJz8tpOwFQzV%3DoXe6R6aS-0ssnXdwDraDS112gnQ0w%40mail.gmail.com >> <https://groups.google.com/d/msgid/golang-nuts/CAF9DLCkTKJz8tpOwFQzV%3DoXe6R6aS-0ssnXdwDraDS112gnQ0w%40mail.gmail.com?utm_medium=email&utm_source=footer> >> . >> > > > -- > V > -- 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/CAF9DLCn_VWFFocEfR3EmXOuAc7RCJjmCgcayCf_EyfH81P9J_w%40mail.gmail.com.