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/CAPUu9suo4k_0qF1HjVAYX0W%2BkNoqrT02cX8pxdoa4F1qx9g0Kg%40mail.gmail.com.