Re: [go-nuts] Re: error handling needs syntactical sugar
On Mon, Sep 11, 2017 at 08:49:30PM +1200, Tim Uckun wrote: > | However, what's great for avoiding straightforward failures becomes a > | nightmare when your goal is to guarantee that no undefined behaviour > | happens > > It seems to me that if this is your goal other languages are more suitable. > Erlang for example is famous for it's error handling capability, > elm guarantees no runtime errors, and some other functional languages can > be proven mathematically at compile time. That's not what the author used the term "no undefined behaviour" for; he referred to the simpler idea of having all possible code paths in the program flow being handled. When you have exceptions, you have two problems: * When they are handled not right at the spot where they are generated, you - Lose track of the points where they may be generated; - Have hard time distinguishing between exceptions occured in different places in the control flow (unless you use super-shallow and super-wide type hierarchy or encode this information in the exceptions). * When new exceptions are added, you have to identify and modify all places where they're handled. That's why typically "exception handling" indeed means having try/catch somewhere at the top level and displaying an error message dialog box (or a HTTP 500 Internal Error page) to the user which is not error handling but "avoiding straightforward failures". As to your particular examples, I'm not familiar with Elm but Erlang stands out for two reasons: - It has the so-called "pattern matching" which, coupled with Erlang's typelessness, allows to implement something which works like "algebraic types". That is, it's easy to write code which asserts specific "shapes" and contents of the values at runtime, and crashes when these expectatiosn are not met. While this is very neat, pretty much of this is covered by Go's static types. - It implements the so-called "supervision trees" which allow you to construct hierarchies of "processes" in which parents get notified when the children crash, and policies for restarting those processes which crashed. While, again, being very neat, their ultimate usefullness is something disputable: when you have a panic in your Go code, this means you have a bug, and given the fact Go is a compiled language, this may mean your whole runtime is an unknown state. All in all, implementation of supervision trees for Go do exist. -- 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. For more options, visit https://groups.google.com/d/optout.
Re: [go-nuts] Re: error handling needs syntactical sugar
| However, what's great for avoiding straightforward failures becomes a | nightmare when your goal is to guarantee that no undefined behaviour | happens It seems to me that if this is your goal other languages are more suitable. Erlang for example is famous for it's error handling capability, elm guarantees no runtime errors, and some other functional languages can be proven mathematically at compile time. Go doesn't take that route which is one of the reasons why it's more popular than those languages :) -- 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. For more options, visit https://groups.google.com/d/optout.
Re: [go-nuts] Re: error handling needs syntactical sugar
On Wed, Sep 06, 2017 at 11:00:08PM -0700, Tim Uckun wrote: > Totally not a go programmer but here are my worthless two cents. > > I don't see anything wrong with the try catch paradigm, you can choose your > granularity. If you want to check every call then you can, if you want to > let a few cluster together you can. You guys make is sound like go style > error handling is the only way to catch errors at every step. That's not > true at all. [...] Actually, I do think there are cases when you don't care which error has actually happened, and where -- you just want to abort processing and quit. Unfortunately, this only works for "batch-style" processing, like shell scripts -- where you want the whole thing to be done, or to fail ASAP should any problem be detected (well, sometimes, though quite much more rarely, you'd even want to merely log errors and continue to chug away with the operations). I have a goto writeup on exceptions bookmarked, which I invite you to read [1]. The key point from it, which pretty much summarizes the idea behind how error handing is done in Go, is: | C++ exceptions … are great for guaranteeing that program doesn't | fail — just wrap the main function in try/catch block and you can | handle all the errors in a single place. | | However, what's great for avoiding straightforward failures becomes a | nightmare when your goal is to guarantee that no undefined behaviour | happens. The decoupling between raising of the exception and handling | it, that makes avoiding failures so easy in C++, makes it virtually | impossible to guarantee that the program never runs info undefined | behaviour. 1. http://250bpm.com/blog:4 -- 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. For more options, visit https://groups.google.com/d/optout.
Re: [go-nuts] Re: error handling needs syntactical sugar
The solution to Close returning an error, is to defer Close() and then have a second Close() with error checking in the happy path. I just wish the io.Closer contract would require, that this has to be safe (= not panic). Luckily it is, for the vast majority of Closers at least. On Fri, Sep 8, 2017 at 6:01 PM, wrote: > P.S. someone else proposed wrapper with error handling in defer. >> IMO it is as bad as watch - spooky, at distance, clunky. >> > > That was me. My background is many years of C++ and it feels natural to me > (RAII). I follow the pattern: there must be defer Close immediately after > acquire action, so it is very obvious in code review if there's a resource > leak or not and if it's panic safe or not. Unfortunately when a defer is > used, another defer is often necessary. > > I read this blog post a while ago: https://joeshaw.org/dont- > defer-close-on-writable-files/ > > He seems to agree with you ("Still, I find this pattern to be a little too > magical."), but his other alternative examples do not seem very > convincing... > > On Friday, September 8, 2017 at 11:03:44 AM UTC+2, ohir wrote: >> >> On Thu, 7 Sep 2017 17:03:06 -0700 (PDT) >> Dorival Pedroso wrote: >> >> >> > Wouldn't be great to have a "syntactical sugar" to make things (at >> least a >> > little bit) simpler in our beloved Go language? >> >> No. Proposed (*also by past me*) "watch" construct is bad for anyone >> reading code, bad for code consistency and is unable to provide any real >> value in spite of high expectations. I coined it as a freshmen to Go then >> I gave it up after few tries to "implement" it with code generator just >> after >> "spooky action at distance is bad" turned out to be so true. >> >> > Simpler would certainly encourage people to handle errors properly >> >> "Watch" is NOT simpler. It bears "at distance" burden. It does not give >> debugging person a way to know which call under watch went wrong. >> The explicitness of if err!=nil { ... } is. >> >> > Of course, we don't need the "watch" command for these. In fact, we >> need >> > nothing special in Go to properly handle these errors. >> >> Yes. And I have learned it weeks after my "I wanna watch" fool. >> (The reason for "watch" was porting an ugly code to check validity of >> many >> fields in complicated financial messages). >> >> Had I have "watch" at hand I would end blindly (albeit automated) >> rewriting >> try/catch spaghetti code for each MT. Fortunately I had no "watch" so I >> got >> to the table, then to the map (for maintenance reasons. See here map: >> https://play.golang.org/p/3PDgjCgPMK . Every try/catch block rewritten >> in >> Go became simple call of validate(&MT, "ABA","SC","RSN") shape). >> >> For SQL call chains you may use "For/Switch" pattern: >> https://play.golang.org/p/0gWarQ8TL7 . >> >> For/Switch is clear and can cope with e.g. retries for a 5 lines more: >> https://play.golang.org/p/CyhIJabzFn >> >> watch: >> for i = 1; retry < 3; i++ { >> if err != nil { >> i-- >> retry++ >> continue >> } >> switch i { >> case 1: >> err = getData(i) >> case 2: >> err = getData(i) >> case 3: >> err = getData(i) >> default: >> break watch >> } >> } >> if err != nil { >> // handle common error >> } >> >> All above patterns have single err handling place yet give back >> information >> where err was set -- something "watch" knows nothing about. >> >> P.S. someone else proposed wrapper with error handling in defer. >> IMO it is as bad as watch - spooky, at distance, clunky. >> >> -- >> Wojciech S. Czarnecki >> << ^oo^ >> OHIR-RIPE >> > -- > 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. > For more options, visit https://groups.google.com/d/optout. > -- 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. For more options, visit https://groups.google.com/d/optout.
Re: [go-nuts] Re: error handling needs syntactical sugar
> > P.S. someone else proposed wrapper with error handling in defer. > IMO it is as bad as watch - spooky, at distance, clunky. > That was me. My background is many years of C++ and it feels natural to me (RAII). I follow the pattern: there must be defer Close immediately after acquire action, so it is very obvious in code review if there's a resource leak or not and if it's panic safe or not. Unfortunately when a defer is used, another defer is often necessary. I read this blog post a while ago: https://joeshaw.org/dont-defer-close-on-writable-files/ He seems to agree with you ("Still, I find this pattern to be a little too magical."), but his other alternative examples do not seem very convincing... On Friday, September 8, 2017 at 11:03:44 AM UTC+2, ohir wrote: > > On Thu, 7 Sep 2017 17:03:06 -0700 (PDT) > Dorival Pedroso > wrote: > > > > Wouldn't be great to have a "syntactical sugar" to make things (at least > a > > little bit) simpler in our beloved Go language? > > No. Proposed (*also by past me*) "watch" construct is bad for anyone > reading code, bad for code consistency and is unable to provide any real > value in spite of high expectations. I coined it as a freshmen to Go then > I gave it up after few tries to "implement" it with code generator just > after > "spooky action at distance is bad" turned out to be so true. > > > Simpler would certainly encourage people to handle errors properly > > "Watch" is NOT simpler. It bears "at distance" burden. It does not give > debugging person a way to know which call under watch went wrong. > The explicitness of if err!=nil { ... } is. > > > Of course, we don't need the "watch" command for these. In fact, we need > > nothing special in Go to properly handle these errors. > > Yes. And I have learned it weeks after my "I wanna watch" fool. > (The reason for "watch" was porting an ugly code to check validity of many > fields in complicated financial messages). > > Had I have "watch" at hand I would end blindly (albeit automated) > rewriting > try/catch spaghetti code for each MT. Fortunately I had no "watch" so I > got > to the table, then to the map (for maintenance reasons. See here map: > https://play.golang.org/p/3PDgjCgPMK . Every try/catch block rewritten in > Go became simple call of validate(&MT, "ABA","SC","RSN") shape). > > For SQL call chains you may use "For/Switch" pattern: > https://play.golang.org/p/0gWarQ8TL7 . > > For/Switch is clear and can cope with e.g. retries for a 5 lines more: > https://play.golang.org/p/CyhIJabzFn > > watch: > for i = 1; retry < 3; i++ { > if err != nil { > i-- > retry++ > continue > } > switch i { > case 1: > err = getData(i) > case 2: > err = getData(i) > case 3: > err = getData(i) > default: > break watch > } > } > if err != nil { > // handle common error > } > > All above patterns have single err handling place yet give back > information > where err was set -- something "watch" knows nothing about. > > P.S. someone else proposed wrapper with error handling in defer. > IMO it is as bad as watch - spooky, at distance, clunky. > > -- > Wojciech S. Czarnecki > << ^oo^ >> OHIR-RIPE > -- 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. For more options, visit https://groups.google.com/d/optout.
Re: [go-nuts] Re: error handling needs syntactical sugar
Sure! I'm happy to listen to the experience of you all and to keep working using the existent approach. Thanks, everyone. Dorival On Friday, September 8, 2017 at 10:29:02 PM UTC+10, Marvin Renich wrote: > > * Dorival Pedroso [170908 02:08]: > > The "watch" strategy would, of course, allow us to do the important > steps > > you've mentioned (e.g. clean up and so on). > > > > For instance: > > watch err != nil { > > // do the important things > > return err > > } > > Except that "do the important things" often depends on which step > produced the error. Now you have a switch statement inside the watch > statement to handle the different "early exit" cases. Instead of having > individual "do step1; clean up after step1" in a linear sequence, you > have "do step1; do step2..." with all of the separate "clean up after > stepN" in a switch statement in a different place. You also have > additional code within the "do step1; do step2..." section to allow the > watch statement to determine which switch case to invoke.This is > much easier to get wrong, harder to modify (especially if you have > nested watch statements), and harder to debug. > > I believe that the Go devs want to encourage suggestions like yours for > Go 2, but this particular one has already been discussed more than once > on this list. You have numerous experienced programmers who have all > used languages with similar constructs telling you that it looks good at > the start, but ends up producing much less maintainable code. Listen to > experience. > > In this particular case, it is not the details that are inconsistent > with the basic philosophy behind the design of the Go language, it is > the entire concept of separating "error" handling from "non-error" > handling. Both are "handling the results" and both belong in the > relative vicinity of the code that produced the results, whether the > results are considered "errors" or "non-errors". > > ...Marvin > > -- 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. For more options, visit https://groups.google.com/d/optout.
Re: [go-nuts] Re: error handling needs syntactical sugar
* Dorival Pedroso [170908 02:08]: > The "watch" strategy would, of course, allow us to do the important steps > you've mentioned (e.g. clean up and so on). > > For instance: > watch err != nil { > // do the important things > return err > } Except that "do the important things" often depends on which step produced the error. Now you have a switch statement inside the watch statement to handle the different "early exit" cases. Instead of having individual "do step1; clean up after step1" in a linear sequence, you have "do step1; do step2..." with all of the separate "clean up after stepN" in a switch statement in a different place. You also have additional code within the "do step1; do step2..." section to allow the watch statement to determine which switch case to invoke.This is much easier to get wrong, harder to modify (especially if you have nested watch statements), and harder to debug. I believe that the Go devs want to encourage suggestions like yours for Go 2, but this particular one has already been discussed more than once on this list. You have numerous experienced programmers who have all used languages with similar constructs telling you that it looks good at the start, but ends up producing much less maintainable code. Listen to experience. In this particular case, it is not the details that are inconsistent with the basic philosophy behind the design of the Go language, it is the entire concept of separating "error" handling from "non-error" handling. Both are "handling the results" and both belong in the relative vicinity of the code that produced the results, whether the results are considered "errors" or "non-errors". ...Marvin -- 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. For more options, visit https://groups.google.com/d/optout.
Re: [go-nuts] Re: error handling needs syntactical sugar
On Thu, 7 Sep 2017 17:03:06 -0700 (PDT) Dorival Pedroso wrote: > Wouldn't be great to have a "syntactical sugar" to make things (at least a > little bit) simpler in our beloved Go language? No. Proposed (*also by past me*) "watch" construct is bad for anyone reading code, bad for code consistency and is unable to provide any real value in spite of high expectations. I coined it as a freshmen to Go then I gave it up after few tries to "implement" it with code generator just after "spooky action at distance is bad" turned out to be so true. > Simpler would certainly encourage people to handle errors properly "Watch" is NOT simpler. It bears "at distance" burden. It does not give debugging person a way to know which call under watch went wrong. The explicitness of if err!=nil { ... } is. > Of course, we don't need the "watch" command for these. In fact, we need > nothing special in Go to properly handle these errors. Yes. And I have learned it weeks after my "I wanna watch" fool. (The reason for "watch" was porting an ugly code to check validity of many fields in complicated financial messages). Had I have "watch" at hand I would end blindly (albeit automated) rewriting try/catch spaghetti code for each MT. Fortunately I had no "watch" so I got to the table, then to the map (for maintenance reasons. See here map: https://play.golang.org/p/3PDgjCgPMK . Every try/catch block rewritten in Go became simple call of validate(&MT, "ABA","SC","RSN") shape). For SQL call chains you may use "For/Switch" pattern: https://play.golang.org/p/0gWarQ8TL7 . For/Switch is clear and can cope with e.g. retries for a 5 lines more: https://play.golang.org/p/CyhIJabzFn watch: for i = 1; retry < 3; i++ { if err != nil { i-- retry++ continue } switch i { case 1: err = getData(i) case 2: err = getData(i) case 3: err = getData(i) default: break watch } } if err != nil { // handle common error } All above patterns have single err handling place yet give back information where err was set -- something "watch" knows nothing about. P.S. someone else proposed wrapper with error handling in defer. IMO it is as bad as watch - spooky, at distance, clunky. -- Wojciech S. Czarnecki << ^oo^ >> OHIR-RIPE -- 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. For more options, visit https://groups.google.com/d/optout.
Re: [go-nuts] Re: error handling needs syntactical sugar
please replace: "will return immediately to the [...]" with "will jump immediately to the [...]" (sorry) On Friday, September 8, 2017 at 4:07:35 PM UTC+10, Dorival Pedroso wrote: > > Hi Dave, > > The "watch" strategy would, of course, allow us to do the important steps > you've mentioned (e.g. clean up and so on). > > For instance: > watch err != nil { > // do the important things > return err > } > > The watch basically "groups common tasks". > > For example, If we have so many tasks, we could do this: > watch errFiles != nil { > cleanup() // do cleanups as Dave suggested > return // this is an synthetic example that doesn't require error > propagation (application dependent, of course) > } > watch errComputations != nil { > // nothing to be done here > return errComputations // return the error because computations failed > } > errFiles = fileOperation("a.txt") // will return immediately to the first > "watch" if errFiles != nil > errFiles = fileOperation("a.txt") // will return immediately to the first > "watch" if errFiles != nil > errFiles = fileOperation("a.txt") // will return immediately to the first > "watch" if errFiles != nil > errCompuations = computeWith("a.txt") // will return immediately to the > second "watch" if errComputations != nil > errCompuations = computeWith("a.txt") // will return immediately to the > second "watch" if errComputations != nil > errCompuations = computeWith("a.txt") // will return immediately to the > second "watch" if errComputations != nil > > Of course, we don't need the "watch" command for these. In fact, we need > nothing special in Go to properly handle these errors. > > Cheers. > Dorival > > > > On Friday, September 8, 2017 at 1:08:47 PM UTC+10, Dave Cheney wrote: >> >> >>> Wouldn't be great to have a "syntactical sugar" to make things (at least >>> a little bit) simpler in our beloved Go language? >>> >> no, I don't think so. >> >> Something that few in in this thread have focused on is the most >> important part of the go error handling story happens *before* the `return >> err` statement >> >> if err != nil { >> // this is the important part >> return err // this is not >> } >> >> Specifically, when an error occurs, cleaning up the accumulated state to >> that point, removing any temporary items like files on disk, transactions, >> etc, so that the caller can attempt to retry the operation if they so >> choose. >> >> Now it happens that most times, thanks to things like defer, there is >> usually nothing to handle in the cleanup phase before returning the error, >> but in my opinion does not take anything away from this being the most >> important part of Go's error handling story. >> > -- 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. For more options, visit https://groups.google.com/d/optout.
Re: [go-nuts] Re: error handling needs syntactical sugar
Hi Dave, The "watch" strategy would, of course, allow us to do the important steps you've mentioned (e.g. clean up and so on). For instance: watch err != nil { // do the important things return err } The watch basically "groups common tasks". For example, If we have so many tasks, we could do this: watch errFiles != nil { cleanup() // do cleanups as Dave suggested return // this is an synthetic example that doesn't require error propagation (application dependent, of course) } watch errComputations != nil { // nothing to be done here return errComputations // return the error because computations failed } errFiles = fileOperation("a.txt") // will return immediately to the first "watch" if errFiles != nil errFiles = fileOperation("a.txt") // will return immediately to the first "watch" if errFiles != nil errFiles = fileOperation("a.txt") // will return immediately to the first "watch" if errFiles != nil errCompuations = computeWith("a.txt") // will return immediately to the second "watch" if errComputations != nil errCompuations = computeWith("a.txt") // will return immediately to the second "watch" if errComputations != nil errCompuations = computeWith("a.txt") // will return immediately to the second "watch" if errComputations != nil Of course, we don't need the "watch" command for these. In fact, we need nothing special in Go to properly handle these errors. Cheers. Dorival On Friday, September 8, 2017 at 1:08:47 PM UTC+10, Dave Cheney wrote: > > >> Wouldn't be great to have a "syntactical sugar" to make things (at least >> a little bit) simpler in our beloved Go language? >> >>> >>> > no, I don't think so. > > Something that few in in this thread have focused on is the most important > part of the go error handling story happens *before* the `return err` > statement > > if err != nil { > // this is the important part > return err // this is not > } > > Specifically, when an error occurs, cleaning up the accumulated state to > that point, removing any temporary items like files on disk, transactions, > etc, so that the caller can attempt to retry the operation if they so > choose. > > Now it happens that most times, thanks to things like defer, there is > usually nothing to handle in the cleanup phase before returning the error, > but in my opinion does not take anything away from this being the most > important part of Go's error handling story. > -- 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. For more options, visit https://groups.google.com/d/optout.
Re: [go-nuts] Re: error handling needs syntactical sugar
> > > Wouldn't be great to have a "syntactical sugar" to make things (at least a > little bit) simpler in our beloved Go language? > >> >> no, I don't think so. Something that few in in this thread have focused on is the most important part of the go error handling story happens *before* the `return err` statement if err != nil { // this is the important part return err // this is not } Specifically, when an error occurs, cleaning up the accumulated state to that point, removing any temporary items like files on disk, transactions, etc, so that the caller can attempt to retry the operation if they so choose. Now it happens that most times, thanks to things like defer, there is usually nothing to handle in the cleanup phase before returning the error, but in my opinion does not take anything away from this being the most important part of Go's error handling story. -- 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. For more options, visit https://groups.google.com/d/optout.
Re: [go-nuts] Re: error handling needs syntactical sugar
Yes, Nigel! try/catch in Python may at times looks uglier that err != nil. I think the reason try/catch didn't bother us in C++ is that we had lots of macros to simplify the work... In Go, we don't have macros but we don't need to wrap things with "try" and just need to "recover" panics, I think. That's why I prefer Martin's first suggestion (no "wrappings"). Wouldn't be great to have a "syntactical sugar" to make things (at least a little bit) simpler in our beloved Go language? Simpler would certainly encourage people to handle errors properly too as Axel pointed out. Cheers! On Friday, September 8, 2017 at 9:34:24 AM UTC+10, Nigel Tao wrote: > > On Thu, Sep 7, 2017 at 4:00 PM, Tim Uckun > > wrote: > > I don't see anything wrong with the try catch paradigm, > > Try-catch makes for shorter code when you're just passing the buck, > but it can be quite complicated when you actually need to handle the > buck. > > My showcase example for this is the exception-ridden code in PEP 380 just > after > > "The statement > RESULT = yield from EXPR > is semantically equivalent to" > > https://www.python.org/dev/peps/pep-0380/ > > I find that Python snippet very hard to understand. In contrast, > writing all those "if err != nil { return nil, err }" might seem > verbose, but I find the control flow much easier to grok, especially > when reviewing somebody else's Go code, or even code written by > 6-months-ago me. > -- 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. For more options, visit https://groups.google.com/d/optout.
Re: [go-nuts] Re: error handling needs syntactical sugar
On Thu, Sep 7, 2017 at 4:00 PM, Tim Uckun wrote: > I don't see anything wrong with the try catch paradigm, Try-catch makes for shorter code when you're just passing the buck, but it can be quite complicated when you actually need to handle the buck. My showcase example for this is the exception-ridden code in PEP 380 just after "The statement RESULT = yield from EXPR is semantically equivalent to" https://www.python.org/dev/peps/pep-0380/ I find that Python snippet very hard to understand. In contrast, writing all those "if err != nil { return nil, err }" might seem verbose, but I find the control flow much easier to grok, especially when reviewing somebody else's Go code, or even code written by 6-months-ago me. -- 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. For more options, visit https://groups.google.com/d/optout.
Re: [go-nuts] Re: error handling needs syntactical sugar
On Thu, 7 Sep 2017 05:00:18 -0700 (PDT) martin.r...@programmfabrik.de wrote: > lhow about this, and it is a construct which can be used not only for > errors: > watch err != nil { > yo1, err = do_stuff1() > yo2, err = do_stuff2() > yo3, err = do_stuff3() > } then { > // handle your error > } Without language change watch: for i := 0; err == nil; i++ { switch i { case 0: err, yo1 = doSomething(i) case 1: err, yo2 = doSomething(i) case 2: err, yo3 = doSomething(i) default: break watch } } if err != nil { // on error do something } https://play.golang.org/p/s6xh1qM4sx > This statement could be used for other cases as well, it is easy to read > and understand, and it saves the programmer from line duplication. Above at least gives to the reader visual breaks (with 'case' lines ;) > Martin > -- Wojciech S. Czarnecki << ^oo^ >> OHIR-RIPE -- 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. For more options, visit https://groups.google.com/d/optout.
Re: [go-nuts] Re: error handling needs syntactical sugar
On Thu, Sep 7, 2017 at 2:41 PM, Tim Uckun wrote: > >I *like* the way go does error passing, *because* it's constrained to > handle errors explicitly. > > But it doesn't though. You can completely ignore the errors if you want. > > This seems to be, at best, a nit-picky uncharitable reading of what I wrote. The context here isn't on whether the compiler should enforce error checks or not, but what the error passing mechanism should be (also note the difference between "being constrained to smth" and "being forced to do smth"). Derailing isn't a particularly good strategy for a discussion, if your objective is to convince the other party. I was proposing that there should be a language construct called errors. > This would be an array. As exceptions are raised the program would push the > errors into this array. At any time you could examine the array to see if > there were errors and if so what they were. When I said "err.pop" I was > indicating that the program would remove the latest error from the stack to > examine it and act on it. > FTR, this isn't a good design (leaving the actual question here, whether we need a new/separate/less explicit error passing mechanism aside). It means that a function can now "return" anything between 0 and infinitely many errors with no way to know statically which. For example func Foo() { for i := 0; i < 1000; i++ { f := os.Open(fmt.Sprintf("%d.txt", i)) if f != nil { f.Close() } } } How would a caller of Foo know how many errors to pop? Or the caller of the caller of Foo? But again, bikeshedding about how an implicit error passing mechanism would look isn't particularly useful, until there is an agreement that it's needed. So far, there doesn't seem to be a consensus on that (and that doesn't seem to be due to a lack of proposals). This would eliminate a lot of boilerplate but conceptually be the same kind > of error handling. Instead of returning a value, err pair you simply return > the value or you raise an exception. The called can check if an error was > raised by calling some method to indicate whether or not the errors array > is empty. > > For example > > x = someMethod() > // if there was an error in there it would populate the array but we don't > have to explicitly receive the err in the return. > ifErr { >// fetch the error > err = errors.pop() >something() > } > > Something like that. > > I also realize that sometimes you may want to halt the app on errors so > there should be a way to bypass this by some kind of declaration. > > -- 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. For more options, visit https://groups.google.com/d/optout.
Re: [go-nuts] Re: error handling needs syntactical sugar
Hi Tim If you want halt the app, you should call panic, that's already a go built-in. Think it would apply to your proposal as well, despite i do not agree with it. Cheers snmed Am Donnerstag, 7. September 2017 14:42:12 UTC+2 schrieb Tim Uckun: > > >I *like* the way go does error passing, *because* it's constrained to > handle errors explicitly. > > But it doesn't though. You can completely ignore the errors if you want. > > > >TBH, no. Not only do I not know what this is supposed to be doing > (err.pop? of what? Why are we assigning to error? What is happening here?), > at best the code seems equivalent to the current code, to me. There is a > function call, a conditional to check for error and then some error > handling. When skimming that code, it would look pretty much identical to > the current idiom. > > > I guess I should have explained it more clearly. > > I was proposing that there should be a language construct called errors. > This would be an array. As exceptions are raised the program would push the > errors into this array. At any time you could examine the array to see if > there were errors and if so what they were. When I said "err.pop" I was > indicating that the program would remove the latest error from the stack to > examine it and act on it. > > This would eliminate a lot of boilerplate but conceptually be the same > kind of error handling. Instead of returning a value, err pair you simply > return the value or you raise an exception. The called can check if an > error was raised by calling some method to indicate whether or not the > errors array is empty. > > For example > > x = someMethod() > // if there was an error in there it would populate the array but we don't > have to explicitly receive the err in the return. > ifErr { >// fetch the error > err = errors.pop() >something() > } > > Something like that. > > I also realize that sometimes you may want to halt the app on errors so > there should be a way to bypass this by some kind of declaration. > > -- 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. For more options, visit https://groups.google.com/d/optout.
Re: [go-nuts] Re: error handling needs syntactical sugar
>I *like* the way go does error passing, *because* it's constrained to handle errors explicitly. But it doesn't though. You can completely ignore the errors if you want. > >TBH, no. Not only do I not know what this is supposed to be doing (err.pop? of what? Why are we assigning to error? What is happening here?), at best the code seems equivalent to the current code, to me. There is a function call, a conditional to check for error and then some error handling. When skimming that code, it would look pretty much identical to the current idiom. I guess I should have explained it more clearly. I was proposing that there should be a language construct called errors. This would be an array. As exceptions are raised the program would push the errors into this array. At any time you could examine the array to see if there were errors and if so what they were. When I said "err.pop" I was indicating that the program would remove the latest error from the stack to examine it and act on it. This would eliminate a lot of boilerplate but conceptually be the same kind of error handling. Instead of returning a value, err pair you simply return the value or you raise an exception. The called can check if an error was raised by calling some method to indicate whether or not the errors array is empty. For example x = someMethod() // if there was an error in there it would populate the array but we don't have to explicitly receive the err in the return. ifErr { // fetch the error err = errors.pop() something() } Something like that. I also realize that sometimes you may want to halt the app on errors so there should be a way to bypass this by some kind of declaration. -- 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. For more options, visit https://groups.google.com/d/optout.
Re: [go-nuts] Re: error handling needs syntactical sugar
I'd hate to debug this: which function has returned the error? What failed, what succeeded? -- 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. For more options, visit https://groups.google.com/d/optout.
Re: [go-nuts] Re: error handling needs syntactical sugar
On Tuesday, September 5, 2017 at 10:39:05 AM UTC+2, Rob 'Commander' Pike wrote: > > If you find that lines like if err != nil are a significant fraction > of non-test code, your code probably needs a better error handling > strategy, not a language change. I have done measurements in the past > and although people complain a lot about the presence of that > statement, it shows up much less often in practice than people claim, > and when it does appear a lot it's usually because the programmer is > not thinking enough about how errors should work. > Well, I can try to find more examples, but whenever you interact with say SQL or other libraries, errors can occur at each call into that library. Very often it is enough to check the errors for one block (think try... catch) The problem with all suggested solutions so far is, that it requires wrapping function calls of some sort. Personally, I don't like this. There are calls (say to interact with an SQL library), and once you start wrapping them in order for an improved error management, the solution is very local and personal and less readable. This does not support Go's idea of producing readable code across developers and styles. After all the responses in this thread, I thought about my proposal a little more carefully, so how about this, and it is a construct which can be used not only for errors: watch err != nil { yo1, err = do_stuff1() yo2, err = do_stuff2() yo3, err = do_stuff3() } then { // handle your error } This statement could be used for other cases as well, it is easy to read and understand, and it saves the programmer from line duplication. Martin -- 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. For more options, visit https://groups.google.com/d/optout.
Re: [go-nuts] Re: error handling needs syntactical sugar
On Thu, Sep 7, 2017 at 8:00 AM, Tim Uckun wrote: > I don't see anything wrong with the try catch paradigm, you can choose > your granularity. If you want to check every call then you can, if you want > to let a few cluster together you can. You guys make is sound like go style > error handling is the only way to catch errors at every step. That's not > true at all. > But the argument is specifically that since you should consider and handle every error specifically, that making *not* doing that easier is bad. Good error handling (even with a try-catch like mechanism) will end up looking pretty much the same as it does today - and bad error handling is something I want to see discouraged. This is akin to someone coming to Haskell and complaining about all the boilerplate they have in their code. "Why do I have to have this 'IO' everywhere? Can't we just make that implicit? And get some loop-constructs up in here, I don't want to have to think about expressing myself via recursion all the time. All other modern languages have iteration concepts, side-effects and mutable data. Maybe be open to some new ideas, instead of assuming everyone else is wrong?" How would you react to that? By saying "oh, yeah, good point, let's build in implicit side-effects and loops and variables"? I don't think so. You'd tell them that functional programming is about carefully containing side-effects. To not have mutable state. And that if they are passing an IO argument everywhere, they should think about restructuring their code and contain IO to the outermost core that actually needs it, while keeping the rest purely functional. I *like* the way go does error passing, *because* it's constrained to handle errors explicitly. And I think there is a good argument to be made, that restructuring your program and rethinking your error handling strategy might help you see it similarly. Surely something can be done about the boilerplate if err != nil maybe > shorten that to iferr or something like that. In fact why can't "err" be a > language construct where you raise something and it goes into an err[] > array. At any time you can check to see what's in there. That would clean > up the code so much. > > result = doSomething() > iferr { >error = err.pop() > } > > Isn't that so much more readable? > TBH, no. Not only do I not know what this is supposed to be doing (err.pop? of what? Why are we assigning to error? What is happening here?), at best the code seems equivalent to the current code, to me. There is a function call, a conditional to check for error and then some error handling. When skimming that code, it would look pretty much identical to the current idiom. And even if we would, for the sake of argument, assume this is more readable; this doesn't mean it justifies a new language construct. The current error-passing mechanism is implemented with basic language primitives that are already there anyway. That's one of its beauties. You could even create checkpoints > > raiseErrors() > // from now on all errors are raised and the program halts > do() > some() > tasks() > collectErrors() > // from now on program doesn't halt but err[] array is populated > do() > other() > things() > dealWithErrArray() // it's global so need to pass it in > raiseErrors() > // back to raising them. > > As I said none of these are particularly nice. Elixir gives you both ways > > > def register({email, password}) do > {:ok, pid} = Membership.connect() > sql = "select * from membership.register($1, $2);" > > case Postgrex.Connection.query(pid, sql, [email, password]) do > {:ok, res} -> > cols = res.columns > [first_row | _] = res.rows > [new_id, validation_token, auth_token, success, message] = first_row > {:ok, %RegistrationResult{ > success: success, > message: message, > new_id: new_id, > authentication_token: auth_token, > validation_token: validation_token > }} > > {:error, err} -> {:error, err} > end > end > > > try do > opts > |> Keyword.fetch!(:source_file) > |> File.read! > rescue > e in KeyError -> IO.puts "missing :source_file option" > e in File.Error -> IO.puts "unable to read source file" > end > > As somebody who has just started learning go I can't find any > justification for the insane amount of boilerplate go error handling > inflicts on the programmer. Surely there is a a better way. > > > > On Wednesday, September 6, 2017 at 8:54:38 PM UTC+12, Henry wrote: >> >> I use what I would call as *error context*. >> >> Here is the simple definition of the *error context*: >> >> type ErrorContext interface { >> ContainsError() bool >> SetError(err error) >> Error() error >> } >> >> Here is how you would use it inside the error-prone function: >> >> func FragileFunction(ctx ErrorContext) { >> if ctx.ContainsError() { >> return >> } >> >> //some processing ... >> //if there is an error >> ctx.Se
[go-nuts] Re: error handling needs syntactical sugar
Agreed, Tim. This discussion helped me to realise that try/catch is pretty good; e.g. we never even bothered discussing this topic in our C++ code http://mechsys.nongnu.org/ at all... In the end of the day, we want to treat ALL errors (obviously...). Go is great that we have two approaches. Right now I'm changing my code to panic/recover and it's looking good (so far): https://github.com/cpmech/gosl/commit/16924f154a848e01a070dc7f86d7f4a3962a0af8 Cheers. Dorival On Thursday, September 7, 2017 at 6:37:21 PM UTC+10, Tim Uckun wrote: > > Totally not a go programmer but here are my worthless two cents. > > > > I don't see anything wrong with the try catch paradigm, you can choose > your granularity. If you want to check every call then you can, if you want > to let a few cluster together you can. You guys make is sound like go style > error handling is the only way to catch errors at every step. That's not > true at all. > > Surely something can be done about the boilerplate if err != nil maybe > shorten that to iferr or something like that. In fact why can't "err" be a > language construct where you raise something and it goes into an err[] > array. At any time you can check to see what's in there. That would clean > up the code so much. > > result = doSomething() > iferr { >error = err.pop() > } > > Isn't that so much more readable? > > You could even create checkpoints > > raiseErrors() > // from now on all errors are raised and the program halts > do() > some() > tasks() > collectErrors() > // from now on program doesn't halt but err[] array is populated > do() > other() > things() > dealWithErrArray() // it's global so need to pass it in > raiseErrors() > // back to raising them. > > As I said none of these are particularly nice. Elixir gives you both ways > > > def register({email, password}) do > {:ok, pid} = Membership.connect() > sql = "select * from membership.register($1, $2);" > > case Postgrex.Connection.query(pid, sql, [email, password]) do > {:ok, res} -> > cols = res.columns > [first_row | _] = res.rows > [new_id, validation_token, auth_token, success, message] = first_row > {:ok, %RegistrationResult{ > success: success, > message: message, > new_id: new_id, > authentication_token: auth_token, > validation_token: validation_token > }} > > {:error, err} -> {:error, err} > end > end > > > try do > opts > |> Keyword.fetch!(:source_file) > |> File.read! > rescue > e in KeyError -> IO.puts "missing :source_file option" > e in File.Error -> IO.puts "unable to read source file" > end > > As somebody who has just started learning go I can't find any > justification for the insane amount of boilerplate go error handling > inflicts on the programmer. Surely there is a a better way. > > > > On Wednesday, September 6, 2017 at 8:54:38 PM UTC+12, Henry wrote: >> >> I use what I would call as *error context*. >> >> Here is the simple definition of the *error context*: >> >> type ErrorContext interface { >> ContainsError() bool >> SetError(err error) >> Error() error >> } >> >> Here is how you would use it inside the error-prone function: >> >> func FragileFunction(ctx ErrorContext) { >> if ctx.ContainsError() { >> return >> } >> >> //some processing ... >> //if there is an error >> ctx.SetError(errors.New("some error")) >> return >> } >> >> >> It allows you to do this: >> >> ctx := NewErrorContext() >> >> fridge := GetFridge(ctx) >> egg := GetEgg(fridge, ctx) >> mixedEgg := MixAndSeason(egg, ctx) >> friedEgg := Fry(mixedEgg, ctx) >> >> if ctx.ContainsError() { >> fmt.Printf("failed to fry eggs: %s", ctx.Error().Error()) >> } >> >> Or you can even do this: >> >> ctxA := NewErrorContext() >> ctxB := NewErrorContext() >> ignored := NewErrorContext() >> >> a := DoSomethingOne(ctxA) >> b := DoSomethingTwo(a, ctxA) >> c,d := DoSomethingThree(b, ctxB) //different context >> if ctxB.ContainsError() { >>c = 1 >>d = 2 >> } >> e := DoSomethingFour(c, d, ctxA) >> if ctxA.ContainsError() { >> fmt.Println("Failed To do A") >> } >> >> DoSomething(e, ignored) //error is ignored >> >> It is up to you how you would implement the error context. >> >> >> On Tuesday, September 5, 2017 at 1:27:20 AM UTC+7, >> marti...@programmfabrik.de wrote: >> >>> Hi guys, >>> >>> at first I though I really like the idea of how Go deals with error >>> management and handling, but the more Go code I look at or try to program, >>> the more I get scared about checking errors every second line in every >>> given block of code. >>> >>> Take a look at this example here from "Build Web Application with >>> Golang": >>> >>> // insert >>> stmt, err := db.Prepare("INSERT INTO userinfo(username, departname, >>> created) values(?,?,?)") >>> if err != nil { >>> // handle error >>> } >>> res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09") >>> if err != nil { >
[go-nuts] Re: error handling needs syntactical sugar
Totally not a go programmer but here are my worthless two cents. I don't see anything wrong with the try catch paradigm, you can choose your granularity. If you want to check every call then you can, if you want to let a few cluster together you can. You guys make is sound like go style error handling is the only way to catch errors at every step. That's not true at all. Surely something can be done about the boilerplate if err != nil maybe shorten that to iferr or something like that. In fact why can't "err" be a language construct where you raise something and it goes into an err[] array. At any time you can check to see what's in there. That would clean up the code so much. result = doSomething() iferr { error = err.pop() } Isn't that so much more readable? You could even create checkpoints raiseErrors() // from now on all errors are raised and the program halts do() some() tasks() collectErrors() // from now on program doesn't halt but err[] array is populated do() other() things() dealWithErrArray() // it's global so need to pass it in raiseErrors() // back to raising them. As I said none of these are particularly nice. Elixir gives you both ways def register({email, password}) do {:ok, pid} = Membership.connect() sql = "select * from membership.register($1, $2);" case Postgrex.Connection.query(pid, sql, [email, password]) do {:ok, res} -> cols = res.columns [first_row | _] = res.rows [new_id, validation_token, auth_token, success, message] = first_row {:ok, %RegistrationResult{ success: success, message: message, new_id: new_id, authentication_token: auth_token, validation_token: validation_token }} {:error, err} -> {:error, err} end end try do opts |> Keyword.fetch!(:source_file) |> File.read! rescue e in KeyError -> IO.puts "missing :source_file option" e in File.Error -> IO.puts "unable to read source file" end As somebody who has just started learning go I can't find any justification for the insane amount of boilerplate go error handling inflicts on the programmer. Surely there is a a better way. On Wednesday, September 6, 2017 at 8:54:38 PM UTC+12, Henry wrote: > > I use what I would call as *error context*. > > Here is the simple definition of the *error context*: > > type ErrorContext interface { > ContainsError() bool > SetError(err error) > Error() error > } > > Here is how you would use it inside the error-prone function: > > func FragileFunction(ctx ErrorContext) { > if ctx.ContainsError() { > return > } > > //some processing ... > //if there is an error > ctx.SetError(errors.New("some error")) > return > } > > > It allows you to do this: > > ctx := NewErrorContext() > > fridge := GetFridge(ctx) > egg := GetEgg(fridge, ctx) > mixedEgg := MixAndSeason(egg, ctx) > friedEgg := Fry(mixedEgg, ctx) > > if ctx.ContainsError() { > fmt.Printf("failed to fry eggs: %s", ctx.Error().Error()) > } > > Or you can even do this: > > ctxA := NewErrorContext() > ctxB := NewErrorContext() > ignored := NewErrorContext() > > a := DoSomethingOne(ctxA) > b := DoSomethingTwo(a, ctxA) > c,d := DoSomethingThree(b, ctxB) //different context > if ctxB.ContainsError() { >c = 1 >d = 2 > } > e := DoSomethingFour(c, d, ctxA) > if ctxA.ContainsError() { > fmt.Println("Failed To do A") > } > > DoSomething(e, ignored) //error is ignored > > It is up to you how you would implement the error context. > > > On Tuesday, September 5, 2017 at 1:27:20 AM UTC+7, > marti...@programmfabrik.de wrote: > >> Hi guys, >> >> at first I though I really like the idea of how Go deals with error >> management and handling, but the more Go code I look at or try to program, >> the more I get scared about checking errors every second line in every >> given block of code. >> >> Take a look at this example here from "Build Web Application with Golang": >> >> // insert >> stmt, err := db.Prepare("INSERT INTO userinfo(username, departname, created) >> values(?,?,?)") >> if err != nil { >> // handle error >> } >> res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09") >> if err != nil { >> // handle error >> } >> id, err := res.LastInsertId() >> if err != nil { >> // handle error >> } >> fmt.Println(id) >> // update >> stmt, err = db.Prepare("update userinfo set username=? where uid=?") >> if err != nil { >> // handle error >> } >> res, err = stmt.Exec("astaxieupdate", id) >> if err != nil { >> // handle error >> } >> affect, err := res.RowsAffected() >> if err != nil { >> // handle error >> } >> >> >> Seriously? And yes, I have read >> https://blog.golang.org/errors-are-values... >> >> The best case reduction I found is: >> >> ... >> res, err = stmt.Exec("astaxieupdate", id) >> checkError(err) >> ... >> >> Still, I need this after each line of calling a function which may return >> an error. >> >> I bet this is not pleasant to do in lar
[go-nuts] Re: error handling needs syntactical sugar
I use what I would call as *error context*. Here is the simple definition of the *error context*: type ErrorContext interface { ContainsError() bool SetError(err error) Error() error } Here is how you would use it inside the error-prone function: func FragileFunction(ctx ErrorContext) { if ctx.ContainsError() { return } //some processing ... //if there is an error ctx.SetError(errors.New("some error")) return } It allows you to do this: ctx := NewErrorContext() fridge := GetFridge(ctx) egg := GetEgg(fridge, ctx) mixedEgg := MixAndSeason(egg, ctx) friedEgg := Fry(mixedEgg, ctx) if ctx.ContainsError() { fmt.Printf("failed to fry eggs: %s", ctx.Error().Error()) } Or you can even do this: ctxA := NewErrorContext() ctxB := NewErrorContext() ignored := NewErrorContext() a := DoSomethingOne(ctxA) b := DoSomethingTwo(a, ctxA) c,d := DoSomethingThree(b, ctxB) //different context if ctxB.ContainsError() { c = 1 d = 2 } e := DoSomethingFour(c, d, ctxA) if ctxA.ContainsError() { fmt.Println("Failed To do A") } DoSomething(e, ignored) //error is ignored It is up to you how you would implement the error context. On Tuesday, September 5, 2017 at 1:27:20 AM UTC+7, marti...@programmfabrik.de wrote: > Hi guys, > > at first I though I really like the idea of how Go deals with error > management and handling, but the more Go code I look at or try to program, > the more I get scared about checking errors every second line in every > given block of code. > > Take a look at this example here from "Build Web Application with Golang": > > // insert > stmt, err := db.Prepare("INSERT INTO userinfo(username, departname, created) > values(?,?,?)") > if err != nil { > // handle error > } > res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09") > if err != nil { > // handle error > } > id, err := res.LastInsertId() > if err != nil { > // handle error > } > fmt.Println(id) > // update > stmt, err = db.Prepare("update userinfo set username=? where uid=?") > if err != nil { > // handle error > } > res, err = stmt.Exec("astaxieupdate", id) > if err != nil { > // handle error > } > affect, err := res.RowsAffected() > if err != nil { > // handle error > } > > > Seriously? And yes, I have read https://blog.golang.org/errors-are-values. > .. > > The best case reduction I found is: > > ... > res, err = stmt.Exec("astaxieupdate", id) > checkError(err) > ... > > Still, I need this after each line of calling a function which may return > an error. > > I bet this is not pleasant to do in larger code bases and it also takes > away focus from what is actually happening. > > 50-80% of all lines of code in my example deal with error handling? > > This is not good. Seriously. > > And don't get me wrong, there is a lot of things I really like, love and > adore about Go, but catching errors needs an improved syntax! > > And I am not proposing try...catch here. > > How about introducing a new piece of syntax > > "watch if " > > which tells the compiler to watch out for changes in a given SimpleStmt > > The same code as above would look like this: > > var err Error > > watch if err != nil { > // handle error(s) > } > > // insert > stmt, err := db.Prepare("INSERT INTO userinfo(username, departname, > created) values(?,?,?)") > res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09") > id, err := res.LastInsertId() > fmt.Println(id) > > // update > stmt, err = db.Prepare("update userinfo set username=? where uid=?") > res, err = stmt.Exec("astaxieupdate", id) > affect, err := res.RowsAffected() > > >- The "watch if" would be executed after each assignment of any of the >variables used in SimpleStmt of the statement. >- Multiple "watch if" would be executed in order or appearance >- The "watch if" could be used like "defer..." inside functions >- The "watch if" would work in its full scope of the watched variables > > I am not a language expert, so may be there is a saner way of expression > what I want to achieve. > > But bottom line is, there should by an easier to read and write way to > deal with errors in Go. > > > Martin > > > > > > -- 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. For more options, visit https://groups.google.com/d/optout.
Re: [go-nuts] Re: error handling needs syntactical sugar
Hi Michael, I fully agree with handling each single error ("health issue") as they are discovered. The idea of "watch" is NOT to replace this procedure. It's just a "syntactic sugar" to do what you are doing already. Cheers. Dorival -- 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. For more options, visit https://groups.google.com/d/optout.
Re: [go-nuts] Re: error handling needs syntactical sugar
...Go is not perfect. But there is subtle magic in this error business. Developers should look closely at errors. Imagine handling them as if you were a doctor and the error was a child's symptom or a test result. Choices: 1. Ask them how they feel, ignore it. Do a test, ignore it. Effectively you are saying "you are well" even if they're not breathing. x, _ := ResultAndErr(a,b,c) 2. Ask them if they feel great and if all test results are normal. If not, send them home. x, err := ResultAndErr(a,b,c) if err != nil { return } 3. Ask them if they feel great and if all test results are normal. If not, send them to a hospital where they can talk to a real doctor. x, err := ResultAndErr(a,b,c) if err != nil { log.Error(err, a,b,c) // or return err } 4. Ask them how the feel and if not good, do tests. Then TREAT THEIR CONDITION. x, err := ResultAndErr(a,b,c) if err ==FirstPossibleProblem { // HANDLE error1 // reset power, wait, etc. } else if err ==SecondPossibleProblem { // HANDLE error2 // lower temperature, send text, start siren, ... } : These four kinds of doctors closely parallel four kinds of programmers. On Tue, Sep 5, 2017 at 3:47 PM, Dorival Pedroso wrote: > Since *defer* "is the last thing to happen", I think this code is all > right: > > func something() (x int, err error) { > watch err != nil { > return > } > res, err = acquireResource() > defer func() { > if err == nil { > err = res.Close() > } > }() > err = abc1() > err = abc2() > err = abc3() > err = abc4() > } > > Also, I'd like to make a general comment (not specific to this case). The > *watch* command doesn't seem (to me) a bad idea. And it could be used for > other purposes too (e.g. as the "watch expression" feature in debuggers or > for logging---yeah we don't really need it...). > > For instance: > > func calculations() { > x := 100.0 > watch x < 0 { > fmt.Printf("hey, x is negative (%d)\n", x) > fmt.Printf("...no worries...\n") > } > x = compute(1,2,3) > x = compute(3,2,1) > x = compute(1,3,2) > } > > It's of course NOT needed at all. Above, we can do the same thing in a > different (probably better) way. > > In fact, *Go is perfect the way it is* and doesn't need any change at all! > > Also, the mechanics (implementation) of *watch* may be "impossible", "too > hard", "confusing" or at least "inefficient"---I don't know (no idea...). > > With an opportunity to work on the Go language implementation, I would > rather spend some time tweaking things to be faster... > > Cheers! > Dorival > > On Wednesday, September 6, 2017 at 1:11:36 AM UTC+10, eko...@gmail.com > wrote: > >> I've been doing something like this for long chains where "handle error" >> is the same: >> >> func something() (x int, err error) { >> defer func() { >> if err != nil { >> // handle error >> } >> }() >> res, err = acquireResource() >> if err == nil { >> defer func() { >> if e := res.Close(); err == nil { >> err = e >> } >> }() >> err = abc1() >> } >> if err == nil { >> err = abc2() >> } >> if err == nil { >> err = abc3() >> } >> if err == nil { >> err = abc4() >> } >> } >> >> How would watch interact with defer? >> >> On Monday, September 4, 2017 at 8:27:20 PM UTC+2, >> marti...@programmfabrik.de wrote: >>> >>> Hi guys, >>> >>> at first I though I really like the idea of how Go deals with error >>> management and handling, but the more Go code I look at or try to program, >>> the more I get scared about checking errors every second line in every >>> given block of code. >>> >>> Take a look at this example here from "Build Web Application with >>> Golang": >>> >>> // insert >>> stmt, err := db.Prepare("INSERT INTO userinfo(username, departname, >>> created) values(?,?,?)") >>> if err != nil { >>> // handle error >>> } >>> res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09") >>> if err != nil { >>> // handle error >>> } >>> id, err := res.LastInsertId() >>> if err != nil { >>> // handle error >>> } >>> fmt.Println(id) >>> // update >>> stmt, err = db.Prepare("update userinfo set username=? where uid=?") >>> if err != nil { >>> // handle error >>> } >>> res, err = stmt.Exec("astaxieupdate", id) >>> if err != nil { >>> // handle error >>> } >>> affect, err := res.RowsAffected() >>> if err != nil { >>> // handle error >>> } >>> >>> >>> Seriously? And yes, I have read https://blog.golang.org/e >>> rrors-are-values... >>> >>> The best case reduction I found is: >>> >>> ... >>> res, err = stmt.Exec("astaxieupdate", id) >>> checkError(err) >>> ... >>> >>> Still, I need this after each line of calling a function which may >>> return an error. >>> >>> I bet this is not pleasant to do in larger code bases and it also takes >>> away focus from what is actually happenin
[go-nuts] Re: error handling needs syntactical sugar
Since *defer* "is the last thing to happen", I think this code is all right: func something() (x int, err error) { watch err != nil { return } res, err = acquireResource() defer func() { if err == nil { err = res.Close() } }() err = abc1() err = abc2() err = abc3() err = abc4() } Also, I'd like to make a general comment (not specific to this case). The *watch* command doesn't seem (to me) a bad idea. And it could be used for other purposes too (e.g. as the "watch expression" feature in debuggers or for logging---yeah we don't really need it...). For instance: func calculations() { x := 100.0 watch x < 0 { fmt.Printf("hey, x is negative (%d)\n", x) fmt.Printf("...no worries...\n") } x = compute(1,2,3) x = compute(3,2,1) x = compute(1,3,2) } It's of course NOT needed at all. Above, we can do the same thing in a different (probably better) way. In fact, *Go is perfect the way it is* and doesn't need any change at all! Also, the mechanics (implementation) of *watch* may be "impossible", "too hard", "confusing" or at least "inefficient"---I don't know (no idea...). With an opportunity to work on the Go language implementation, I would rather spend some time tweaking things to be faster... Cheers! Dorival On Wednesday, September 6, 2017 at 1:11:36 AM UTC+10, eko...@gmail.com wrote: > > I've been doing something like this for long chains where "handle error" > is the same: > > func something() (x int, err error) { > defer func() { > if err != nil { > // handle error > } > }() > res, err = acquireResource() > if err == nil { > defer func() { > if e := res.Close(); err == nil { > err = e > } > }() > err = abc1() > } > if err == nil { > err = abc2() > } > if err == nil { > err = abc3() > } > if err == nil { > err = abc4() > } > } > > How would watch interact with defer? > > On Monday, September 4, 2017 at 8:27:20 PM UTC+2, > marti...@programmfabrik.de wrote: >> >> Hi guys, >> >> at first I though I really like the idea of how Go deals with error >> management and handling, but the more Go code I look at or try to program, >> the more I get scared about checking errors every second line in every >> given block of code. >> >> Take a look at this example here from "Build Web Application with Golang": >> >> // insert >> stmt, err := db.Prepare("INSERT INTO userinfo(username, departname, created) >> values(?,?,?)") >> if err != nil { >> // handle error >> } >> res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09") >> if err != nil { >> // handle error >> } >> id, err := res.LastInsertId() >> if err != nil { >> // handle error >> } >> fmt.Println(id) >> // update >> stmt, err = db.Prepare("update userinfo set username=? where uid=?") >> if err != nil { >> // handle error >> } >> res, err = stmt.Exec("astaxieupdate", id) >> if err != nil { >> // handle error >> } >> affect, err := res.RowsAffected() >> if err != nil { >> // handle error >> } >> >> >> Seriously? And yes, I have read >> https://blog.golang.org/errors-are-values... >> >> The best case reduction I found is: >> >> ... >> res, err = stmt.Exec("astaxieupdate", id) >> checkError(err) >> ... >> >> Still, I need this after each line of calling a function which may return >> an error. >> >> I bet this is not pleasant to do in larger code bases and it also takes >> away focus from what is actually happening. >> >> 50-80% of all lines of code in my example deal with error handling? >> >> This is not good. Seriously. >> >> And don't get me wrong, there is a lot of things I really like, love and >> adore about Go, but catching errors needs an improved syntax! >> >> And I am not proposing try...catch here. >> >> How about introducing a new piece of syntax >> >> "watch if " >> >> which tells the compiler to watch out for changes in a given SimpleStmt >> >> The same code as above would look like this: >> >> var err Error >> >> watch if err != nil { >> // handle error(s) >> } >> >> // insert >> stmt, err := db.Prepare("INSERT INTO userinfo(username, departname, >> created) values(?,?,?)") >> res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09") >> id, err := res.LastInsertId() >> fmt.Println(id) >> >> // update >> stmt, err = db.Prepare("update userinfo set username=? where uid=?") >> res, err = stmt.Exec("astaxieupdate", id) >> affect, err := res.RowsAffected() >> >> >>- The "watch if" would be executed after each assignment of any of >>the variables used in SimpleStmt of the statement. >>- Multiple "watch if" would be executed in order or appearance >>- The "watch if" could be used like "defer..." inside functions >>- The "watch if" would work in its full scope of the watched variables >> >> I am not a language expert, so may be there
[go-nuts] Re: error handling needs syntactical sugar
Hi, yes we need the check condition you had before in defer. That seems fine. But there may be some other problems I haven't thought of. Cheers -- 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. For more options, visit https://groups.google.com/d/optout.
[go-nuts] Re: error handling needs syntactical sugar
What about? func something() (x int, err error) { watch err != nil { // this is only required to watch out in case "err" ever becomes non-nil return // the error will propagate outside (same as "return err") } res, err = acquireResource() // will return straightway (because we cannot close the resource...) defer func() { e := res.Close() return 0, e }() err = abc1() // if err != nil, the "watcher" would return right here with the most recent error (message) err = abc2() // This seems better than "accumulating" the error in an internal data structure err = abc3() // because abc2() and so on wouldn't even work if abc1() had failed err = abc4() // But of course, another err1, err2, ... could be used instead } (Again, just an idea...) Cheers! On Wednesday, September 6, 2017 at 1:11:36 AM UTC+10, eko...@gmail.com wrote: > > I've been doing something like this for long chains where "handle error" > is the same: > > func something() (x int, err error) { > defer func() { > if err != nil { > // handle error > } > }() > res, err = acquireResource() > if err == nil { > defer func() { > if e := res.Close(); err == nil { > err = e > } > }() > err = abc1() > } > if err == nil { > err = abc2() > } > if err == nil { > err = abc3() > } > if err == nil { > err = abc4() > } > } > > How would watch interact with defer? > > On Monday, September 4, 2017 at 8:27:20 PM UTC+2, > marti...@programmfabrik.de wrote: >> >> Hi guys, >> >> at first I though I really like the idea of how Go deals with error >> management and handling, but the more Go code I look at or try to program, >> the more I get scared about checking errors every second line in every >> given block of code. >> >> Take a look at this example here from "Build Web Application with Golang": >> >> // insert >> stmt, err := db.Prepare("INSERT INTO userinfo(username, departname, created) >> values(?,?,?)") >> if err != nil { >> // handle error >> } >> res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09") >> if err != nil { >> // handle error >> } >> id, err := res.LastInsertId() >> if err != nil { >> // handle error >> } >> fmt.Println(id) >> // update >> stmt, err = db.Prepare("update userinfo set username=? where uid=?") >> if err != nil { >> // handle error >> } >> res, err = stmt.Exec("astaxieupdate", id) >> if err != nil { >> // handle error >> } >> affect, err := res.RowsAffected() >> if err != nil { >> // handle error >> } >> >> >> Seriously? And yes, I have read >> https://blog.golang.org/errors-are-values... >> >> The best case reduction I found is: >> >> ... >> res, err = stmt.Exec("astaxieupdate", id) >> checkError(err) >> ... >> >> Still, I need this after each line of calling a function which may return >> an error. >> >> I bet this is not pleasant to do in larger code bases and it also takes >> away focus from what is actually happening. >> >> 50-80% of all lines of code in my example deal with error handling? >> >> This is not good. Seriously. >> >> And don't get me wrong, there is a lot of things I really like, love and >> adore about Go, but catching errors needs an improved syntax! >> >> And I am not proposing try...catch here. >> >> How about introducing a new piece of syntax >> >> "watch if " >> >> which tells the compiler to watch out for changes in a given SimpleStmt >> >> The same code as above would look like this: >> >> var err Error >> >> watch if err != nil { >> // handle error(s) >> } >> >> // insert >> stmt, err := db.Prepare("INSERT INTO userinfo(username, departname, >> created) values(?,?,?)") >> res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09") >> id, err := res.LastInsertId() >> fmt.Println(id) >> >> // update >> stmt, err = db.Prepare("update userinfo set username=? where uid=?") >> res, err = stmt.Exec("astaxieupdate", id) >> affect, err := res.RowsAffected() >> >> >>- The "watch if" would be executed after each assignment of any of >>the variables used in SimpleStmt of the statement. >>- Multiple "watch if" would be executed in order or appearance >>- The "watch if" could be used like "defer..." inside functions >>- The "watch if" would work in its full scope of the watched variables >> >> I am not a language expert, so may be there is a saner way of expression >> what I want to achieve. >> >> But bottom line is, there should by an easier to read and write way to >> deal with errors in Go. >> >> >> Martin >> >> >> >> >> >> -- 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. For more options, visit https://groups.google.com/d/optout.
[go-nuts] Re: error handling needs syntactical sugar
What about the following? func something() (x int, err error) { watch err != nil { // this is only required to watch out in case "err" ever becomes non-nil return // the error will propagate outside (same as "return err") } res, err = acquireResource() // will return straightway (because we cannot close the resource...) defer func() { e := res.Close() // if err != nil, the "watcher" would return the message return 0, e }() err = abc1() // if err != nil, the "watcher" would return right here with the most recent error (message) err = abc2() // This seems better than "accumulating" the error in an internal data structure err = abc3() // because abc2() and so on wouldn't even work if abc1() had failed err = abc4() // But of course, another err1, err2, ... could be used instead } (again, just an idea...) Cheers! On Wednesday, September 6, 2017 at 1:11:36 AM UTC+10, eko...@gmail.com wrote: > > I've been doing something like this for long chains where "handle error" > is the same: > > func something() (x int, err error) { > defer func() { > if err != nil { > // handle error > } > }() > res, err = acquireResource() > if err == nil { > defer func() { > if e := res.Close(); err == nil { > err = e > } > }() > err = abc1() > } > if err == nil { > err = abc2() > } > if err == nil { > err = abc3() > } > if err == nil { > err = abc4() > } > } > > How would watch interact with defer? > > On Monday, September 4, 2017 at 8:27:20 PM UTC+2, > marti...@programmfabrik.de wrote: >> >> Hi guys, >> >> at first I though I really like the idea of how Go deals with error >> management and handling, but the more Go code I look at or try to program, >> the more I get scared about checking errors every second line in every >> given block of code. >> >> Take a look at this example here from "Build Web Application with Golang": >> >> // insert >> stmt, err := db.Prepare("INSERT INTO userinfo(username, departname, created) >> values(?,?,?)") >> if err != nil { >> // handle error >> } >> res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09") >> if err != nil { >> // handle error >> } >> id, err := res.LastInsertId() >> if err != nil { >> // handle error >> } >> fmt.Println(id) >> // update >> stmt, err = db.Prepare("update userinfo set username=? where uid=?") >> if err != nil { >> // handle error >> } >> res, err = stmt.Exec("astaxieupdate", id) >> if err != nil { >> // handle error >> } >> affect, err := res.RowsAffected() >> if err != nil { >> // handle error >> } >> >> >> Seriously? And yes, I have read >> https://blog.golang.org/errors-are-values... >> >> The best case reduction I found is: >> >> ... >> res, err = stmt.Exec("astaxieupdate", id) >> checkError(err) >> ... >> >> Still, I need this after each line of calling a function which may return >> an error. >> >> I bet this is not pleasant to do in larger code bases and it also takes >> away focus from what is actually happening. >> >> 50-80% of all lines of code in my example deal with error handling? >> >> This is not good. Seriously. >> >> And don't get me wrong, there is a lot of things I really like, love and >> adore about Go, but catching errors needs an improved syntax! >> >> And I am not proposing try...catch here. >> >> How about introducing a new piece of syntax >> >> "watch if " >> >> which tells the compiler to watch out for changes in a given SimpleStmt >> >> The same code as above would look like this: >> >> var err Error >> >> watch if err != nil { >> // handle error(s) >> } >> >> // insert >> stmt, err := db.Prepare("INSERT INTO userinfo(username, departname, >> created) values(?,?,?)") >> res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09") >> id, err := res.LastInsertId() >> fmt.Println(id) >> >> // update >> stmt, err = db.Prepare("update userinfo set username=? where uid=?") >> res, err = stmt.Exec("astaxieupdate", id) >> affect, err := res.RowsAffected() >> >> >>- The "watch if" would be executed after each assignment of any of >>the variables used in SimpleStmt of the statement. >>- Multiple "watch if" would be executed in order or appearance >>- The "watch if" could be used like "defer..." inside functions >>- The "watch if" would work in its full scope of the watched variables >> >> I am not a language expert, so may be there is a saner way of expression >> what I want to achieve. >> >> But bottom line is, there should by an easier to read and write way to >> deal with errors in Go. >> >> >> Martin >> >> >> >> >> >> -- 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. For more options, vi
[go-nuts] Re: error handling needs syntactical sugar
What about the following? func something() (x int, err error) { watch err != nil { // this is only required to watch out in case "err" ever becomes non-nil return // the error will propagate outside (same as "return err") } res, err = acquireResource() // will return straightway? (because we cannot close the // resource...) defer func() { e := res.Close() // if err != nil, the "watcher" would return the message return 0, e }() err = abc1() // if err != nil, the "watcher" would return right here with the most recent error (message) err = abc2() // This seems better than "accumulating" the error in an internal data structure err = abc3() // because abc2() and so on wouldn't even work if abc1() had failed err = abc4() // But of course, another err1, err2, ... could be used instead } There might be something wrong in the code above (sorry)... don't know... Again...just an idea... Cheers. Dorival On Wednesday, September 6, 2017 at 1:11:36 AM UTC+10, eko...@gmail.com wrote: > > I've been doing something like this for long chains where "handle error" > is the same: > > func something() (x int, err error) { > defer func() { > if err != nil { > // handle error > } > }() > res, err = acquireResource() > if err == nil { > defer func() { > if e := res.Close(); err == nil { > err = e > } > }() > err = abc1() > } > if err == nil { > err = abc2() > } > if err == nil { > err = abc3() > } > if err == nil { > err = abc4() > } > } > > How would watch interact with defer? > > On Monday, September 4, 2017 at 8:27:20 PM UTC+2, > marti...@programmfabrik.de wrote: >> >> Hi guys, >> >> at first I though I really like the idea of how Go deals with error >> management and handling, but the more Go code I look at or try to program, >> the more I get scared about checking errors every second line in every >> given block of code. >> >> Take a look at this example here from "Build Web Application with Golang": >> >> // insert >> stmt, err := db.Prepare("INSERT INTO userinfo(username, departname, created) >> values(?,?,?)") >> if err != nil { >> // handle error >> } >> res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09") >> if err != nil { >> // handle error >> } >> id, err := res.LastInsertId() >> if err != nil { >> // handle error >> } >> fmt.Println(id) >> // update >> stmt, err = db.Prepare("update userinfo set username=? where uid=?") >> if err != nil { >> // handle error >> } >> res, err = stmt.Exec("astaxieupdate", id) >> if err != nil { >> // handle error >> } >> affect, err := res.RowsAffected() >> if err != nil { >> // handle error >> } >> >> >> Seriously? And yes, I have read >> https://blog.golang.org/errors-are-values... >> >> The best case reduction I found is: >> >> ... >> res, err = stmt.Exec("astaxieupdate", id) >> checkError(err) >> ... >> >> Still, I need this after each line of calling a function which may return >> an error. >> >> I bet this is not pleasant to do in larger code bases and it also takes >> away focus from what is actually happening. >> >> 50-80% of all lines of code in my example deal with error handling? >> >> This is not good. Seriously. >> >> And don't get me wrong, there is a lot of things I really like, love and >> adore about Go, but catching errors needs an improved syntax! >> >> And I am not proposing try...catch here. >> >> How about introducing a new piece of syntax >> >> "watch if " >> >> which tells the compiler to watch out for changes in a given SimpleStmt >> >> The same code as above would look like this: >> >> var err Error >> >> watch if err != nil { >> // handle error(s) >> } >> >> // insert >> stmt, err := db.Prepare("INSERT INTO userinfo(username, departname, >> created) values(?,?,?)") >> res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09") >> id, err := res.LastInsertId() >> fmt.Println(id) >> >> // update >> stmt, err = db.Prepare("update userinfo set username=? where uid=?") >> res, err = stmt.Exec("astaxieupdate", id) >> affect, err := res.RowsAffected() >> >> >>- The "watch if" would be executed after each assignment of any of >>the variables used in SimpleStmt of the statement. >>- Multiple "watch if" would be executed in order or appearance >>- The "watch if" could be used like "defer..." inside functions >>- The "watch if" would work in its full scope of the watched variables >> >> I am not a language expert, so may be there is a saner way of expression >> what I want to achieve. >> >> But bottom line is, there should by an easier to read and write way to >> deal with errors in Go. >> >> >> Martin >> >> >> >> >> >> -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from thi
[go-nuts] Re: error handling needs syntactical sugar
I've been doing something like this for long chains where "handle error" is the same: func something() (x int, err error) { defer func() { if err != nil { // handle error } }() res, err = acquireResource() if err == nil { defer func() { if e := res.Close(); err == nil { err = e } }() err = abc1() } if err == nil { err = abc2() } if err == nil { err = abc3() } if err == nil { err = abc4() } } How would watch interact with defer? On Monday, September 4, 2017 at 8:27:20 PM UTC+2, marti...@programmfabrik.de wrote: > > Hi guys, > > at first I though I really like the idea of how Go deals with error > management and handling, but the more Go code I look at or try to program, > the more I get scared about checking errors every second line in every > given block of code. > > Take a look at this example here from "Build Web Application with Golang": > > // insert > stmt, err := db.Prepare("INSERT INTO userinfo(username, departname, created) > values(?,?,?)") > if err != nil { > // handle error > } > res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09") > if err != nil { > // handle error > } > id, err := res.LastInsertId() > if err != nil { > // handle error > } > fmt.Println(id) > // update > stmt, err = db.Prepare("update userinfo set username=? where uid=?") > if err != nil { > // handle error > } > res, err = stmt.Exec("astaxieupdate", id) > if err != nil { > // handle error > } > affect, err := res.RowsAffected() > if err != nil { > // handle error > } > > > Seriously? And yes, I have read https://blog.golang.org/errors-are-values. > .. > > The best case reduction I found is: > > ... > res, err = stmt.Exec("astaxieupdate", id) > checkError(err) > ... > > Still, I need this after each line of calling a function which may return > an error. > > I bet this is not pleasant to do in larger code bases and it also takes > away focus from what is actually happening. > > 50-80% of all lines of code in my example deal with error handling? > > This is not good. Seriously. > > And don't get me wrong, there is a lot of things I really like, love and > adore about Go, but catching errors needs an improved syntax! > > And I am not proposing try...catch here. > > How about introducing a new piece of syntax > > "watch if " > > which tells the compiler to watch out for changes in a given SimpleStmt > > The same code as above would look like this: > > var err Error > > watch if err != nil { > // handle error(s) > } > > // insert > stmt, err := db.Prepare("INSERT INTO userinfo(username, departname, > created) values(?,?,?)") > res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09") > id, err := res.LastInsertId() > fmt.Println(id) > > // update > stmt, err = db.Prepare("update userinfo set username=? where uid=?") > res, err = stmt.Exec("astaxieupdate", id) > affect, err := res.RowsAffected() > > >- The "watch if" would be executed after each assignment of any of the >variables used in SimpleStmt of the statement. >- Multiple "watch if" would be executed in order or appearance >- The "watch if" could be used like "defer..." inside functions >- The "watch if" would work in its full scope of the watched variables > > I am not a language expert, so may be there is a saner way of expression > what I want to achieve. > > But bottom line is, there should by an easier to read and write way to > deal with errors in Go. > > > Martin > > > > > > -- 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. For more options, visit https://groups.google.com/d/optout.
Re: [go-nuts] Re: error handling needs syntactical sugar
Or you know, just panic ... errors as value are a convention, not a language construct. panic/defer ARE a language construct. I personally give the choice in my API, Must prefixed methods that panic or regular methods that return an error. The obvious advantage of panics is that the developer actually gets a stack trace for free, not need for 50 different packages that wrap errors just to get a stack trace. Le mardi 5 septembre 2017 11:17:13 UTC+2, Dorival Pedroso a écrit : > > Thanks again, Rob. > > The blog post (https://blog.golang.org/errors-are-values) does shed some > light. > > One of the ideas is to hold the *err* variable in a structure. I will > definitively use this more often (I do have many structures and never > thought of doing this!)---Thanks! > > The other idea is to create a wrapping structure (e.g. type errWriter struct > {w io.Writer; err error}) just to keep hold of the *err* variable. In > this case, I'd prefer to return *err* in my "pure function" (I also have > many of those; e.g. for "mathematical computations"). In this case, I > actually don't mind returning and checking the err variable as long as I > don't need the wrapper. > > Now, this piece of code: > > ew := &errWriter{w: fd} > ew.write(p0[a:b]) > ew.write(p1[c:d]) > ew.write(p2[e:f]) > // and so on > if ew.err != nil { > return ew.err > } > > > could easily (?, I don't know) be replaced by: > > *watch* err != nil { > > return err > > } > err = fd.write(p0[a:b]) > err = fd.write(p1[c:d]) > err = fd.write(p2[e:f]) > // and so on > > > and we wouldn't need the wrapping structure... (sorry for being so lazy ;-) > > By the way, maybe one day I'll attend a GoCon and will bring a laptop for > sure... > > Cheers. > Dorival > > > On Tuesday, September 5, 2017 at 6:39:05 PM UTC+10, Rob 'Commander' Pike > wrote: >> >> If you find that lines like if err != nil are a significant fraction >> of non-test code, your code probably needs a better error handling >> strategy, not a language change. I have done measurements in the past >> and although people complain a lot about the presence of that >> statement, it shows up much less often in practice than people claim, >> and when it does appear a lot it's usually because the programmer is >> not thinking enough about how errors should work. >> >> Please reread that blog post. >> >> -rob >> >> >> On Tue, Sep 5, 2017 at 5:45 PM, Dorival Pedroso >> wrote: >> > Fair enough. This would be perfect. Cheers >> > >> > >> > On Tuesday, September 5, 2017 at 5:42:26 PM UTC+10, >> > marti...@programmfabrik.de wrote: >> >> >> >> Dorival, >> >> >> >> I think we can celebrate already if we achieve anything with this >> >> discussion. Let's not ask for too much, plus let's not make it too >> >> complicated. >> >> >> >> I think your proposed "watch err", hides too much and does too little. >> >> >> >> You can simply write (the inline code editor is broken, BTW) >> >> >> >> func ... { >> >> var err >> >> watch err != nil { >> >> // handle error >> >> return >> >> } >> >> // do stuff >> >> yo1, err := do_stuff1() >> >> yo2, err := do_stuff2() >> >> yo3, err := do_stuff3() >> >> } >> >> >> >> >> >> Martin >> >> >> >> >> >> On Tuesday, September 5, 2017 at 9:32:50 AM UTC+2, Dorival Pedroso >> wrote: >> >>> >> >>> Hi Martin; >> >>> >> >>> What about two commands "watch" and "watchif"? >> >>> >> >>> The first works as the "var" command and the second as the "if" >> command. >> >>> >> >>> "watch" does: >> >>> >> >>> In a function with error as an output (anywhere): returns in case the >> err >> >>> declared with watch err (or watch myerror) becomes non-nil. watch err >> would >> >>> declare err" as var does. Most use cases would put watch err at the >> >>> beginning of a function (although this is optional as it is with >> defer) >> >>> In a test function; aka TestSomething(something *testing.T), watch >> err >> >>> error would declare err (or watch myerror error) and if an error >> occurs, it >> >>> would call something.FailNow() after (printing the error >> message?---still >> >>> need to think this part better) >> >>> In the main function: watch err error would print the error message >> (or >> >>> maybe pipe to stderr) and os.Exist(1) >> >>> watchif err != nil {HERE} would be more powerful because it would >> allow >> >>> us to do other things. But the mechanism is similar (as you proposed >> >>> initially): if err becomes non-nil anywhere, the execution in HERE >> would >> >>> take place. >> >>> >> >>> Cheers! >> >>> >> >>> >> >>> On Tuesday, September 5, 2017 at 4:55:59 PM UTC+10, >> >>> marti...@programmfabrik.de wrote: >> >> Hi Dorival, >> >> thanks for supporting me with my idea. >> >> And yes, after writing my post yesterday I was thinking, "watchif" >> or >> even simply "watch". >> >> And yes, today I am more in favor of simply "watch". >>
Re: [go-nuts] Re: error handling needs syntactical sugar
Thanks again, Rob. The blog post (https://blog.golang.org/errors-are-values) does shed some light. One of the ideas is to hold the *err* variable in a structure. I will definitively use this more often (I do have many structures and never thought of doing this!)---Thanks! The other idea is to create a wrapping structure (e.g. type errWriter struct {w io.Writer; err error}) just to keep hold of the *err* variable. In this case, I'd prefer to return *err* in my "pure function" (I also have many of those; e.g. for "mathematical computations"). In this case, I actually don't mind returning and checking the err variable as long as I don't need the wrapper. Now, this piece of code: ew := &errWriter{w: fd} ew.write(p0[a:b]) ew.write(p1[c:d]) ew.write(p2[e:f]) // and so on if ew.err != nil { return ew.err } could easily (?, I don't know) be replaced by: *watch* err != nil { return err } err = fd.write(p0[a:b]) err = fd.write(p1[c:d]) err = fd.write(p2[e:f]) // and so on and we wouldn't need the wrapping structure... (sorry for being so lazy ;-) By the way, maybe one day I'll attend a GoCon and will bring a laptop for sure... Cheers. Dorival On Tuesday, September 5, 2017 at 6:39:05 PM UTC+10, Rob 'Commander' Pike wrote: > > If you find that lines like if err != nil are a significant fraction > of non-test code, your code probably needs a better error handling > strategy, not a language change. I have done measurements in the past > and although people complain a lot about the presence of that > statement, it shows up much less often in practice than people claim, > and when it does appear a lot it's usually because the programmer is > not thinking enough about how errors should work. > > Please reread that blog post. > > -rob > > > On Tue, Sep 5, 2017 at 5:45 PM, Dorival Pedroso > wrote: > > Fair enough. This would be perfect. Cheers > > > > > > On Tuesday, September 5, 2017 at 5:42:26 PM UTC+10, > > marti...@programmfabrik.de wrote: > >> > >> Dorival, > >> > >> I think we can celebrate already if we achieve anything with this > >> discussion. Let's not ask for too much, plus let's not make it too > >> complicated. > >> > >> I think your proposed "watch err", hides too much and does too little. > >> > >> You can simply write (the inline code editor is broken, BTW) > >> > >> func ... { > >> var err > >> watch err != nil { > >> // handle error > >> return > >> } > >> // do stuff > >> yo1, err := do_stuff1() > >> yo2, err := do_stuff2() > >> yo3, err := do_stuff3() > >> } > >> > >> > >> Martin > >> > >> > >> On Tuesday, September 5, 2017 at 9:32:50 AM UTC+2, Dorival Pedroso > wrote: > >>> > >>> Hi Martin; > >>> > >>> What about two commands "watch" and "watchif"? > >>> > >>> The first works as the "var" command and the second as the "if" > command. > >>> > >>> "watch" does: > >>> > >>> In a function with error as an output (anywhere): returns in case the > err > >>> declared with watch err (or watch myerror) becomes non-nil. watch err > would > >>> declare err" as var does. Most use cases would put watch err at the > >>> beginning of a function (although this is optional as it is with > defer) > >>> In a test function; aka TestSomething(something *testing.T), watch err > >>> error would declare err (or watch myerror error) and if an error > occurs, it > >>> would call something.FailNow() after (printing the error > message?---still > >>> need to think this part better) > >>> In the main function: watch err error would print the error message > (or > >>> maybe pipe to stderr) and os.Exist(1) > >>> watchif err != nil {HERE} would be more powerful because it would > allow > >>> us to do other things. But the mechanism is similar (as you proposed > >>> initially): if err becomes non-nil anywhere, the execution in HERE > would > >>> take place. > >>> > >>> Cheers! > >>> > >>> > >>> On Tuesday, September 5, 2017 at 4:55:59 PM UTC+10, > >>> marti...@programmfabrik.de wrote: > > Hi Dorival, > > thanks for supporting me with my idea. > > And yes, after writing my post yesterday I was thinking, "watchif" or > even simply "watch". > > And yes, today I am more in favor of simply "watch". > > And yes, we can constrain this to the context of one function (like > defer), I am ok with that. > > What you are describing how you work with errors and how you spent > hours > adding > > if err != nil > > that is exactly my point. > > On could nicely write this > > ... > watch err!=nil { > handle_sql_error(err) > } > ... > > Of course, watch could also be used to not watch out for errors but > any > other places where new values to get assigned to variables. > > Martin > >> > >> > > -- > > You received this message because
Re: [go-nuts] Re: error handling needs syntactical sugar
Exactly: a good amount of "if err != nil" appears in my tests (334 out of 569). I'll try to re-think the other cases... (e.g. https://github.com/cpmech/gosl/blob/master/la/blas2.go) No complaints here, by the way! Just enjoying this marvellous language! I'll read the blog post. Cheers. On Tuesday, September 5, 2017 at 6:39:05 PM UTC+10, Rob 'Commander' Pike wrote: > > If you find that lines like if err != nil are a significant fraction > of non-test code, your code probably needs a better error handling > strategy, not a language change. I have done measurements in the past > and although people complain a lot about the presence of that > statement, it shows up much less often in practice than people claim, > and when it does appear a lot it's usually because the programmer is > not thinking enough about how errors should work. > > Please reread that blog post. > > -rob > > > On Tue, Sep 5, 2017 at 5:45 PM, Dorival Pedroso > wrote: > > Fair enough. This would be perfect. Cheers > > > > > > On Tuesday, September 5, 2017 at 5:42:26 PM UTC+10, > > marti...@programmfabrik.de wrote: > >> > >> Dorival, > >> > >> I think we can celebrate already if we achieve anything with this > >> discussion. Let's not ask for too much, plus let's not make it too > >> complicated. > >> > >> I think your proposed "watch err", hides too much and does too little. > >> > >> You can simply write (the inline code editor is broken, BTW) > >> > >> func ... { > >> var err > >> watch err != nil { > >> // handle error > >> return > >> } > >> // do stuff > >> yo1, err := do_stuff1() > >> yo2, err := do_stuff2() > >> yo3, err := do_stuff3() > >> } > >> > >> > >> Martin > >> > >> > >> On Tuesday, September 5, 2017 at 9:32:50 AM UTC+2, Dorival Pedroso > wrote: > >>> > >>> Hi Martin; > >>> > >>> What about two commands "watch" and "watchif"? > >>> > >>> The first works as the "var" command and the second as the "if" > command. > >>> > >>> "watch" does: > >>> > >>> In a function with error as an output (anywhere): returns in case the > err > >>> declared with watch err (or watch myerror) becomes non-nil. watch err > would > >>> declare err" as var does. Most use cases would put watch err at the > >>> beginning of a function (although this is optional as it is with > defer) > >>> In a test function; aka TestSomething(something *testing.T), watch err > >>> error would declare err (or watch myerror error) and if an error > occurs, it > >>> would call something.FailNow() after (printing the error > message?---still > >>> need to think this part better) > >>> In the main function: watch err error would print the error message > (or > >>> maybe pipe to stderr) and os.Exist(1) > >>> watchif err != nil {HERE} would be more powerful because it would > allow > >>> us to do other things. But the mechanism is similar (as you proposed > >>> initially): if err becomes non-nil anywhere, the execution in HERE > would > >>> take place. > >>> > >>> Cheers! > >>> > >>> > >>> On Tuesday, September 5, 2017 at 4:55:59 PM UTC+10, > >>> marti...@programmfabrik.de wrote: > > Hi Dorival, > > thanks for supporting me with my idea. > > And yes, after writing my post yesterday I was thinking, "watchif" or > even simply "watch". > > And yes, today I am more in favor of simply "watch". > > And yes, we can constrain this to the context of one function (like > defer), I am ok with that. > > What you are describing how you work with errors and how you spent > hours > adding > > if err != nil > > that is exactly my point. > > On could nicely write this > > ... > watch err!=nil { > handle_sql_error(err) > } > ... > > Of course, watch could also be used to not watch out for errors but > any > other places where new values to get assigned to variables. > > Martin > >> > >> > > -- > > 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 . > > For more options, visit https://groups.google.com/d/optout. > -- 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. For more options, visit https://groups.google.com/d/optout.
Re: [go-nuts] Re: error handling needs syntactical sugar
If you find that lines like if err != nil are a significant fraction of non-test code, your code probably needs a better error handling strategy, not a language change. I have done measurements in the past and although people complain a lot about the presence of that statement, it shows up much less often in practice than people claim, and when it does appear a lot it's usually because the programmer is not thinking enough about how errors should work. Please reread that blog post. -rob On Tue, Sep 5, 2017 at 5:45 PM, Dorival Pedroso wrote: > Fair enough. This would be perfect. Cheers > > > On Tuesday, September 5, 2017 at 5:42:26 PM UTC+10, > marti...@programmfabrik.de wrote: >> >> Dorival, >> >> I think we can celebrate already if we achieve anything with this >> discussion. Let's not ask for too much, plus let's not make it too >> complicated. >> >> I think your proposed "watch err", hides too much and does too little. >> >> You can simply write (the inline code editor is broken, BTW) >> >> func ... { >> var err >> watch err != nil { >> // handle error >> return >> } >> // do stuff >> yo1, err := do_stuff1() >> yo2, err := do_stuff2() >> yo3, err := do_stuff3() >> } >> >> >> Martin >> >> >> On Tuesday, September 5, 2017 at 9:32:50 AM UTC+2, Dorival Pedroso wrote: >>> >>> Hi Martin; >>> >>> What about two commands "watch" and "watchif"? >>> >>> The first works as the "var" command and the second as the "if" command. >>> >>> "watch" does: >>> >>> In a function with error as an output (anywhere): returns in case the err >>> declared with watch err (or watch myerror) becomes non-nil. watch err would >>> declare err" as var does. Most use cases would put watch err at the >>> beginning of a function (although this is optional as it is with defer) >>> In a test function; aka TestSomething(something *testing.T), watch err >>> error would declare err (or watch myerror error) and if an error occurs, it >>> would call something.FailNow() after (printing the error message?---still >>> need to think this part better) >>> In the main function: watch err error would print the error message (or >>> maybe pipe to stderr) and os.Exist(1) >>> watchif err != nil {HERE} would be more powerful because it would allow >>> us to do other things. But the mechanism is similar (as you proposed >>> initially): if err becomes non-nil anywhere, the execution in HERE would >>> take place. >>> >>> Cheers! >>> >>> >>> On Tuesday, September 5, 2017 at 4:55:59 PM UTC+10, >>> marti...@programmfabrik.de wrote: Hi Dorival, thanks for supporting me with my idea. And yes, after writing my post yesterday I was thinking, "watchif" or even simply "watch". And yes, today I am more in favor of simply "watch". And yes, we can constrain this to the context of one function (like defer), I am ok with that. What you are describing how you work with errors and how you spent hours adding if err != nil that is exactly my point. On could nicely write this ... watch err!=nil { handle_sql_error(err) } ... Of course, watch could also be used to not watch out for errors but any other places where new values to get assigned to variables. Martin >> >> > -- > 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. > For more options, visit https://groups.google.com/d/optout. -- 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. For more options, visit https://groups.google.com/d/optout.
[go-nuts] Re: error handling needs syntactical sugar
Fair enough. This would be perfect. Cheers On Tuesday, September 5, 2017 at 5:42:26 PM UTC+10, marti...@programmfabrik.de wrote: > > Dorival, > > I think we can celebrate already if we achieve anything with this > discussion. Let's not ask for too much, plus let's not make it too > complicated. > > I think your proposed "watch err", hides too much and does too little. > > You can simply write (the inline code editor is broken, BTW) > > func ... { > var err > watch err != nil { > // handle error > return > } > // do stuff > yo1, err := do_stuff1() > yo2, err := do_stuff2() > yo3, err := do_stuff3() > } > > > Martin > > > On Tuesday, September 5, 2017 at 9:32:50 AM UTC+2, Dorival Pedroso wrote: >> >> Hi Martin; >> >> What about two commands "*watch*" and "*watchif*"? >> >> The first works as the "*var*" command and the second as the "*if*" >> command. >> >> "*watch*" does: >> >>1. In a function with *error* as an output (anywhere): returns in >>case the *err* declared with *watch err* (or *watch myerror*) becomes >>non-nil. *watch err* would declare *err*" as *var* does. Most use >>cases would put *watch err* at the beginning of a function (although >>this is optional as it is with *defer*) >>2. In a test function; aka TestSomething(something *testing.T), *watch >>err error* would declare *err* (or *watch myerror error*) and if an >>error occurs, it would call something.FailNow() after (printing the error >>message?---still need to think this part better) >>3. In the main function: *watch err error* would print the error >>message (or maybe pipe to stderr) and os.Exist(1) >>4. *watchif err != nil {HERE}* would be more powerful because it >>would allow us to do other things. But the mechanism is similar (as you >>proposed initially): if *err* becomes non-nil anywhere, the execution >>in *HERE* would take place. >> >> Cheers! >> >> >> On Tuesday, September 5, 2017 at 4:55:59 PM UTC+10, >> marti...@programmfabrik.de wrote: >>> >>> Hi Dorival, >>> >>> thanks for supporting me with my idea. >>> >>> And yes, after writing my post yesterday I was thinking, "watchif" or >>> even simply "watch". >>> >>> And yes, today I am more in favor of simply *"watch"*. >>> >>> And yes, we can constrain this to the context of one function (like >>> defer), I am ok with that. >>> >>> What you are describing how you work with errors and how you spent hours >>> adding >>> >>> *if err != nil* >>> >>> that is *exactly* my point. >>> >>> On could nicely write this >>> >>> ... >>> watch err!=nil { >>> handle_sql_error(err) >>> } >>> ... >>> >>> Of course, watch could also be used to not watch out for errors but any >>> other places where new values to get assigned to variables. >>> >>> Martin >>> > -- 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. For more options, visit https://groups.google.com/d/optout.
[go-nuts] Re: error handling needs syntactical sugar
Dorival, I think we can celebrate already if we achieve anything with this discussion. Let's not ask for too much, plus let's not make it too complicated. I think your proposed "watch err", hides too much and does too little. You can simply write (the inline code editor is broken, BTW) func ... { var err watch err != nil { // handle error return } // do stuff yo1, err := do_stuff1() yo2, err := do_stuff2() yo3, err := do_stuff3() } Martin On Tuesday, September 5, 2017 at 9:32:50 AM UTC+2, Dorival Pedroso wrote: > > Hi Martin; > > What about two commands "*watch*" and "*watchif*"? > > The first works as the "*var*" command and the second as the "*if*" > command. > > "*watch*" does: > >1. In a function with *error* as an output (anywhere): returns in case >the *err* declared with *watch err* (or *watch myerror*) becomes >non-nil. *watch err* would declare *err*" as *var* does. Most use >cases would put *watch err* at the beginning of a function (although >this is optional as it is with *defer*) >2. In a test function; aka TestSomething(something *testing.T), *watch >err error* would declare *err* (or *watch myerror error*) and if an >error occurs, it would call something.FailNow() after (printing the error >message?---still need to think this part better) >3. In the main function: *watch err error* would print the error >message (or maybe pipe to stderr) and os.Exist(1) >4. *watchif err != nil {HERE}* would be more powerful because it would >allow us to do other things. But the mechanism is similar (as you proposed >initially): if *err* becomes non-nil anywhere, the execution in *HERE* >would take place. > > Cheers! > > > On Tuesday, September 5, 2017 at 4:55:59 PM UTC+10, > marti...@programmfabrik.de wrote: >> >> Hi Dorival, >> >> thanks for supporting me with my idea. >> >> And yes, after writing my post yesterday I was thinking, "watchif" or >> even simply "watch". >> >> And yes, today I am more in favor of simply *"watch"*. >> >> And yes, we can constrain this to the context of one function (like >> defer), I am ok with that. >> >> What you are describing how you work with errors and how you spent hours >> adding >> >> *if err != nil* >> >> that is *exactly* my point. >> >> On could nicely write this >> >> ... >> watch err!=nil { >> handle_sql_error(err) >> } >> ... >> >> Of course, watch could also be used to not watch out for errors but any >> other places where new values to get assigned to variables. >> >> Martin >> >>> -- 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. For more options, visit https://groups.google.com/d/optout.
[go-nuts] Re: error handling needs syntactical sugar
Hi Martin; What about two commands "*watch*" and "*watchif*"? The first works as the "*var*" command and the second as the "*if*" command. "*watch*" does: 1. In a function with *error* as an output (anywhere): returns in case the *err* declared with *watch err* (or *watch myerror*) becomes non-nil. *watch err* would declare *err*" as *var* does. Most use cases would put *watch err* at the beginning of a function (although this is optional as it is with *defer*) 2. In a test function; aka TestSomething(something *testing.T), *watch err error* would declare *err* (or *watch myerror error*) and if an error occurs, it would call something.FailNow() after (printing the error message?---still need to think this part better) 3. In the main function: *watch err error* would print the error message (or maybe pipe to stderr) and os.Exist(1) 4. *watchif err != nil {HERE}* would be more powerful because it would allow us to do other things. But the mechanism is similar (as you proposed initially): if *err* becomes non-nil anywhere, the execution in *HERE* would take place. Cheers! On Tuesday, September 5, 2017 at 4:55:59 PM UTC+10, marti...@programmfabrik.de wrote: > > Hi Dorival, > > thanks for supporting me with my idea. > > And yes, after writing my post yesterday I was thinking, "watchif" or even > simply "watch". > > And yes, today I am more in favor of simply *"watch"*. > > And yes, we can constrain this to the context of one function (like > defer), I am ok with that. > > What you are describing how you work with errors and how you spent hours > adding > > *if err != nil* > > that is *exactly* my point. > > On could nicely write this > > ... > watch err!=nil { > handle_sql_error(err) > } > ... > > Of course, watch could also be used to not watch out for errors but any > other places where new values to get assigned to variables. > > Martin > >> >>> -- 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. For more options, visit https://groups.google.com/d/optout.
[go-nuts] Re: error handling needs syntactical sugar
Hi Dorival, thanks for supporting me with my idea. And yes, after writing my post yesterday I was thinking, "watchif" or even simply "watch". And yes, today I am more in favor of simply *"watch"*. And yes, we can constrain this to the context of one function (like defer), I am ok with that. What you are describing how you work with errors and how you spent hours adding *if err != nil* that is *exactly* my point. On could nicely write this ... watch err!=nil { handle_sql_error(err) } ... Of course, watch could also be used to not watch out for errors but any other places where new values to get assigned to variables. Martin > >> -- 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. For more options, visit https://groups.google.com/d/optout.
[go-nuts] Re: error handling needs syntactical sugar
On Monday, September 4, 2017 at 10:48:06 PM UTC+2, Tamás Gulácsi wrote: > > Why do you Prepare a statement if you don't reuse it? Just use a db.Exec. Just wanted to show a pattern which I see very often in Go code. Its not a working example, and I am not asking for improvements in that code. But concretes aside: error handling IS important! > Yes it is. But as my example shows, it should not get annoying. > But if such code bothers you, create some helper type / function: see one > Andy+Brad pair programming video where they create an errWriter struct > which is an io.Writer, and just writes to the underlyin Write. Untill the > first error. From then on it always returns the fist error. > The problem with ANY error handling solution within the existing Go syntax will require one of three things: - Wrap the call which you need to check the error for - Wrap the check into a function, to save code lines - Do some tricks to check the error at the end of a block Neither one of these methods is satisfying for me. I need to be able to produce readable, concise code which does the right thing. -- 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. For more options, visit https://groups.google.com/d/optout.
[go-nuts] Re: error handling needs syntactical sugar
I forgot (again) to say that in this case the error would just be returned. In other words, `watch err` would just check if `err != nil` and then return. The other cases (test, main) would be as explained earlier (FailNow(), Exit(1)) On Tuesday, September 5, 2017 at 10:14:16 AM UTC+10, Dorival Pedroso wrote: > > Hi, the `watch err` could also work in "APIs" that already return "error". > > For instance: > package myapi > > func First() (err error) { > watch err > err = internalFunction(1,2,3) > err = internalFunction(3,2,1) > err = internalFunction(1,3,2) > } > > > > > On Tuesday, September 5, 2017 at 4:27:20 AM UTC+10, > marti...@programmfabrik.de wrote: >> >> Hi guys, >> >> at first I though I really like the idea of how Go deals with error >> management and handling, but the more Go code I look at or try to program, >> the more I get scared about checking errors every second line in every >> given block of code. >> >> Take a look at this example here from "Build Web Application with Golang": >> >> // insert >> stmt, err := db.Prepare("INSERT INTO userinfo(username, departname, created) >> values(?,?,?)") >> if err != nil { >> // handle error >> } >> res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09") >> if err != nil { >> // handle error >> } >> id, err := res.LastInsertId() >> if err != nil { >> // handle error >> } >> fmt.Println(id) >> // update >> stmt, err = db.Prepare("update userinfo set username=? where uid=?") >> if err != nil { >> // handle error >> } >> res, err = stmt.Exec("astaxieupdate", id) >> if err != nil { >> // handle error >> } >> affect, err := res.RowsAffected() >> if err != nil { >> // handle error >> } >> >> >> Seriously? And yes, I have read >> https://blog.golang.org/errors-are-values... >> >> The best case reduction I found is: >> >> ... >> res, err = stmt.Exec("astaxieupdate", id) >> checkError(err) >> ... >> >> Still, I need this after each line of calling a function which may return >> an error. >> >> I bet this is not pleasant to do in larger code bases and it also takes >> away focus from what is actually happening. >> >> 50-80% of all lines of code in my example deal with error handling? >> >> This is not good. Seriously. >> >> And don't get me wrong, there is a lot of things I really like, love and >> adore about Go, but catching errors needs an improved syntax! >> >> And I am not proposing try...catch here. >> >> How about introducing a new piece of syntax >> >> "watch if " >> >> which tells the compiler to watch out for changes in a given SimpleStmt >> >> The same code as above would look like this: >> >> var err Error >> >> watch if err != nil { >> // handle error(s) >> } >> >> // insert >> stmt, err := db.Prepare("INSERT INTO userinfo(username, departname, >> created) values(?,?,?)") >> res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09") >> id, err := res.LastInsertId() >> fmt.Println(id) >> >> // update >> stmt, err = db.Prepare("update userinfo set username=? where uid=?") >> res, err = stmt.Exec("astaxieupdate", id) >> affect, err := res.RowsAffected() >> >> >>- The "watch if" would be executed after each assignment of any of >>the variables used in SimpleStmt of the statement. >>- Multiple "watch if" would be executed in order or appearance >>- The "watch if" could be used like "defer..." inside functions >>- The "watch if" would work in its full scope of the watched variables >> >> I am not a language expert, so may be there is a saner way of expression >> what I want to achieve. >> >> But bottom line is, there should by an easier to read and write way to >> deal with errors in Go. >> >> >> Martin >> >> >> >> >> >> -- 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. For more options, visit https://groups.google.com/d/optout.
[go-nuts] Re: error handling needs syntactical sugar
Hi, the `watch err` could also work in "APIs" that already return "error". For instance: package myapi func First() (err error) { watch err err = internalFunction(1,2,3) err = internalFunction(3,2,1) err = internalFunction(1,3,2) } On Tuesday, September 5, 2017 at 4:27:20 AM UTC+10, marti...@programmfabrik.de wrote: > > Hi guys, > > at first I though I really like the idea of how Go deals with error > management and handling, but the more Go code I look at or try to program, > the more I get scared about checking errors every second line in every > given block of code. > > Take a look at this example here from "Build Web Application with Golang": > > // insert > stmt, err := db.Prepare("INSERT INTO userinfo(username, departname, created) > values(?,?,?)") > if err != nil { > // handle error > } > res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09") > if err != nil { > // handle error > } > id, err := res.LastInsertId() > if err != nil { > // handle error > } > fmt.Println(id) > // update > stmt, err = db.Prepare("update userinfo set username=? where uid=?") > if err != nil { > // handle error > } > res, err = stmt.Exec("astaxieupdate", id) > if err != nil { > // handle error > } > affect, err := res.RowsAffected() > if err != nil { > // handle error > } > > > Seriously? And yes, I have read https://blog.golang.org/errors-are-values. > .. > > The best case reduction I found is: > > ... > res, err = stmt.Exec("astaxieupdate", id) > checkError(err) > ... > > Still, I need this after each line of calling a function which may return > an error. > > I bet this is not pleasant to do in larger code bases and it also takes > away focus from what is actually happening. > > 50-80% of all lines of code in my example deal with error handling? > > This is not good. Seriously. > > And don't get me wrong, there is a lot of things I really like, love and > adore about Go, but catching errors needs an improved syntax! > > And I am not proposing try...catch here. > > How about introducing a new piece of syntax > > "watch if " > > which tells the compiler to watch out for changes in a given SimpleStmt > > The same code as above would look like this: > > var err Error > > watch if err != nil { > // handle error(s) > } > > // insert > stmt, err := db.Prepare("INSERT INTO userinfo(username, departname, > created) values(?,?,?)") > res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09") > id, err := res.LastInsertId() > fmt.Println(id) > > // update > stmt, err = db.Prepare("update userinfo set username=? where uid=?") > res, err = stmt.Exec("astaxieupdate", id) > affect, err := res.RowsAffected() > > >- The "watch if" would be executed after each assignment of any of the >variables used in SimpleStmt of the statement. >- Multiple "watch if" would be executed in order or appearance >- The "watch if" could be used like "defer..." inside functions >- The "watch if" would work in its full scope of the watched variables > > I am not a language expert, so may be there is a saner way of expression > what I want to achieve. > > But bottom line is, there should by an easier to read and write way to > deal with errors in Go. > > > Martin > > > > > > -- 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. For more options, visit https://groups.google.com/d/optout.
[go-nuts] Re: error handling needs syntactical sugar
by the way, above, I was thinking of `watch` as a counterpart of `var`... On Tuesday, September 5, 2017 at 8:56:24 AM UTC+10, Dorival Pedroso wrote: > > Hi, > > Error management in Go is perfect! > > But I like the idea of `watch` (may we drop the `if`?) > > So, `watch` would work in the context of a function like `defer`. However, > this would effectively become a `catcher` for errors (instead of `panics`) > within the `defer` function, right? > > Also, I think `watch` would effectively be a "conditioned defer". > > Once, I've spent hours adding `if err != nil { ... }` elsewhere in my > code. Lately, I've started using two auxiliary functions just for > readability: > > In tests, I use: > func status(tst *testing.T, err error) { > if err != nil { > tst.Errorf("ERROR: %v\n", err) > tst.FailNow() > } > } > > func TestBessel01(tst *testing.T) { > dat, err := ReadTable("data/as-9-bessel-integer-big.cmp") > status(tst, err) > ... > } > > In "main functions", I use: > func status(err error) { > if err != nil { > io.Pf("ERROR: %v\n", err) > os.Exit(1) > } > } > > I (try to) check the errors everywhere in the API and these "syntax > sugars" are only required at the final stages ("test mode" or "main > function"). > > So, `watch` could be something like: > func TestBessel01(tst *testing.T) { > watch err error // the compiler could detect that we're on "test" mode > and then return when err != nil > dat, err := ReadTable("data/as-9-bessel-integer-big.cmp") > err = ComputeWithData(dat) > ... > err = DoSomethingElse(dat) > ... > } > > In "main functions": > func main() { > watch err error // the compiler would detect that we're on "main > function" mode and then Exit(1) > err := ComputeWithData(...) > } > > The command `watch` could even be used for different purposes; e.g. when > something that should be isn't. > > Cheers. > D > > > On Tuesday, September 5, 2017 at 4:27:20 AM UTC+10, > marti...@programmfabrik.de wrote: >> >> Hi guys, >> >> at first I though I really like the idea of how Go deals with error >> management and handling, but the more Go code I look at or try to program, >> the more I get scared about checking errors every second line in every >> given block of code. >> >> Take a look at this example here from "Build Web Application with Golang": >> >> // insert >> stmt, err := db.Prepare("INSERT INTO userinfo(username, departname, created) >> values(?,?,?)") >> if err != nil { >> // handle error >> } >> res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09") >> if err != nil { >> // handle error >> } >> id, err := res.LastInsertId() >> if err != nil { >> // handle error >> } >> fmt.Println(id) >> // update >> stmt, err = db.Prepare("update userinfo set username=? where uid=?") >> if err != nil { >> // handle error >> } >> res, err = stmt.Exec("astaxieupdate", id) >> if err != nil { >> // handle error >> } >> affect, err := res.RowsAffected() >> if err != nil { >> // handle error >> } >> >> >> Seriously? And yes, I have read >> https://blog.golang.org/errors-are-values... >> >> The best case reduction I found is: >> >> ... >> res, err = stmt.Exec("astaxieupdate", id) >> checkError(err) >> ... >> >> Still, I need this after each line of calling a function which may return >> an error. >> >> I bet this is not pleasant to do in larger code bases and it also takes >> away focus from what is actually happening. >> >> 50-80% of all lines of code in my example deal with error handling? >> >> This is not good. Seriously. >> >> And don't get me wrong, there is a lot of things I really like, love and >> adore about Go, but catching errors needs an improved syntax! >> >> And I am not proposing try...catch here. >> >> How about introducing a new piece of syntax >> >> "watch if " >> >> which tells the compiler to watch out for changes in a given SimpleStmt >> >> The same code as above would look like this: >> >> var err Error >> >> watch if err != nil { >> // handle error(s) >> } >> >> // insert >> stmt, err := db.Prepare("INSERT INTO userinfo(username, departname, >> created) values(?,?,?)") >> res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09") >> id, err := res.LastInsertId() >> fmt.Println(id) >> >> // update >> stmt, err = db.Prepare("update userinfo set username=? where uid=?") >> res, err = stmt.Exec("astaxieupdate", id) >> affect, err := res.RowsAffected() >> >> >>- The "watch if" would be executed after each assignment of any of >>the variables used in SimpleStmt of the statement. >>- Multiple "watch if" would be executed in order or appearance >>- The "watch if" could be used like "defer..." inside functions >>- The "watch if" would work in its full scope of the watched variables >> >> I am not a language expert, so may be there is a saner way of expression >> what I want to achieve. >> >> But bottom line is, there should by an easier to read and wri
[go-nuts] Re: error handling needs syntactical sugar
Hi, Error management in Go is perfect! But I like the idea of `watch` (may we drop the `if`?) So, `watch` would work in the context of a function like `defer`. However, this would effectively become a `catcher` for errors (instead of `panics`) within the `defer` function, right? Also, I think `watch` would effectively be a "conditioned defer". Once, I've spent hours adding `if err != nil { ... }` elsewhere in my code. Lately, I've started using two auxiliary functions just for readability: In tests, I use: func status(tst *testing.T, err error) { if err != nil { tst.Errorf("ERROR: %v\n", err) tst.FailNow() } } func TestBessel01(tst *testing.T) { dat, err := ReadTable("data/as-9-bessel-integer-big.cmp") status(tst, err) ... } In "main functions", I use: func status(err error) { if err != nil { io.Pf("ERROR: %v\n", err) os.Exit(1) } } I (try to) check the errors everywhere in the API and these "syntax sugars" are only required at the final stages ("test mode" or "main function"). So, `watch` could be something like: func TestBessel01(tst *testing.T) { watch err error // the compiler could detect that we're on "test" mode and then return when err != nil dat, err := ReadTable("data/as-9-bessel-integer-big.cmp") err = ComputeWithData(dat) ... err = DoSomethingElse(dat) ... } In "main functions": func main() { watch err error // the compiler would detect that we're on "main function" mode and then Exit(1) err := ComputeWithData(...) } The command `watch` could even be used for different purposes; e.g. when something that should be isn't. Cheers. D On Tuesday, September 5, 2017 at 4:27:20 AM UTC+10, marti...@programmfabrik.de wrote: > > Hi guys, > > at first I though I really like the idea of how Go deals with error > management and handling, but the more Go code I look at or try to program, > the more I get scared about checking errors every second line in every > given block of code. > > Take a look at this example here from "Build Web Application with Golang": > > // insert > stmt, err := db.Prepare("INSERT INTO userinfo(username, departname, created) > values(?,?,?)") > if err != nil { > // handle error > } > res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09") > if err != nil { > // handle error > } > id, err := res.LastInsertId() > if err != nil { > // handle error > } > fmt.Println(id) > // update > stmt, err = db.Prepare("update userinfo set username=? where uid=?") > if err != nil { > // handle error > } > res, err = stmt.Exec("astaxieupdate", id) > if err != nil { > // handle error > } > affect, err := res.RowsAffected() > if err != nil { > // handle error > } > > > Seriously? And yes, I have read https://blog.golang.org/errors-are-values. > .. > > The best case reduction I found is: > > ... > res, err = stmt.Exec("astaxieupdate", id) > checkError(err) > ... > > Still, I need this after each line of calling a function which may return > an error. > > I bet this is not pleasant to do in larger code bases and it also takes > away focus from what is actually happening. > > 50-80% of all lines of code in my example deal with error handling? > > This is not good. Seriously. > > And don't get me wrong, there is a lot of things I really like, love and > adore about Go, but catching errors needs an improved syntax! > > And I am not proposing try...catch here. > > How about introducing a new piece of syntax > > "watch if " > > which tells the compiler to watch out for changes in a given SimpleStmt > > The same code as above would look like this: > > var err Error > > watch if err != nil { > // handle error(s) > } > > // insert > stmt, err := db.Prepare("INSERT INTO userinfo(username, departname, > created) values(?,?,?)") > res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09") > id, err := res.LastInsertId() > fmt.Println(id) > > // update > stmt, err = db.Prepare("update userinfo set username=? where uid=?") > res, err = stmt.Exec("astaxieupdate", id) > affect, err := res.RowsAffected() > > >- The "watch if" would be executed after each assignment of any of the >variables used in SimpleStmt of the statement. >- Multiple "watch if" would be executed in order or appearance >- The "watch if" could be used like "defer..." inside functions >- The "watch if" would work in its full scope of the watched variables > > I am not a language expert, so may be there is a saner way of expression > what I want to achieve. > > But bottom line is, there should by an easier to read and write way to > deal with errors in Go. > > > Martin > > > > > > -- 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. For more options, visit https://groups.google.com/d/optout.