Re: [go-nuts] Re: Error handling

2023-08-04 Thread Miguel Angel Rivera Notararigo
On Fri, Aug 4, 2023, 13:57 Harri L  wrote:

> Yes, we can handle Go errors without language changes; that’s true. But
> how we should annotate errors? The presented version of CopyFile leads to
> following 'stuttering':
> cannot copy '/tmpfs/play' to './tmp33/not-exist.txt': cannot create
> destination: open ./tmp33/not-exist.txt: no such file or directory
>
>
You will notice there is repeated information, and it is because os.Create
adds meaningless context to the error message ("open
./tmp33/not-exist.txt"), file path is owned by caller, and caller should
handle its problems. It should be:

cannot copy '/tmpfs/play' to './tmp33/not-exist.txt': cannot create
destination: no such file or directory

I thinks its pretty easy to read. But if you prefer sed "s/: /\n\n/g":

cannot copy '/tmpfs/play' to './tmp33/not-exist.txt'

cannot create destination

no such file or directory

You don't even need a stack trace to know where it failed.

If you use pre-declared errors, you can even go further and do some
handling programmatically, like "errros.Is(err, Retry)" for retrying
without any complicated dependency.


You can get compact but informative error messages just by following K
> annotation rules:
>
>1. Annotate the function you are implementing
>2. Let the functions that you are calling do their own job
>
> copy file: open ./tmp33/not-exist.txt: no such file or directory
>
>
For me (personal opinion), that message is not easy to understand.

copy file
Is this a log message telling me it is copying some file? or is it an error
message?
open ./tmp33/not-exist.txt
Oh, cool, it was a log message, it is opening a file now, keep it going
buddy, you can copy that file :)
no such file or directory
Well, it is a failure, I guess. But now I don't know where it failed, is
that source or destination?

With previous message:

cannot copy '/tmpfs/play' to './tmp33/not-exist.txt'
No! why you do this to me?
cannot create destination
But WHY!? I have been so nice to you 'not-exist.txt'
no such file or directory
Oh, you don't even exist haha sorry, drama moment

(We would never get that error because os.Create creates the file, but I am
using your example)

Using specific annotation is a different topic, but the primary goal of
this error messages is being hints for developers. For end users you will
be probably using translations or anything else.

All of this is just basic error propagation, which can be automated to
> avoid annoying human errors. You can see three different error annotation
> scenarios of the FileCopy implementations in this playground
> .
>
> And the function itself is compact as well — and fully automated (tip:
> change the name of the function):
> func copyFile(src, dst string) (err error) { defer err2.Handle() r :=
> try.To1(os.Open(src)) defer r.Close() w := try.To1(os.Create(dst)) defer
> err2.Handle(, func() { os.Remove(dst) }) defer w.Close()
> try.To1(io.Copy(w, r)) return nil }
> ​
>

Not sure, but this looks like try-catch exceptions in Go.

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/CAF9DLCkGDsDOf9qUqmtux0D55Csc2n6%3DcKw_G9zUJBbSTi3SJA%40mail.gmail.com.


Re: [go-nuts] Re: Error handling

2023-08-04 Thread Harri L


Yes, we can handle Go errors without language changes; that’s true. But how 
we should annotate errors? The presented version of CopyFile leads to 
following 'stuttering':
cannot copy '/tmpfs/play' to './tmp33/not-exist.txt': cannot create 
destination: open ./tmp33/not-exist.txt: no such file or directory 

You can get compact but informative error messages just by following K 
annotation rules:

   1. Annotate the function you are implementing 
   2. Let the functions that you are calling do their own job 

copy file: open ./tmp33/not-exist.txt: no such file or directory 

All of this is just basic error propagation, which can be automated to 
avoid annoying human errors. You can see three different error annotation 
scenarios of the FileCopy implementations in this playground 
.

And the function itself is compact as well — and fully automated (tip: 
change the name of the function):
func copyFile(src, dst string) (err error) { defer err2.Handle() r := 
try.To1(os.Open(src)) defer r.Close() w := try.To1(os.Create(dst)) defer 
err2.Handle(, func() { os.Remove(dst) }) defer w.Close() 
try.To1(io.Copy(w, r)) return nil } 
​
On Friday, August 4, 2023 at 6:07:52 AM UTC+3 Miguel Angel Rivera 
Notararigo wrote:

> func CopyFile(src, dst string) error {
> r, err := os.Open(src)
> if err != nil {
> return fmt.Errorf("copy %s %s: %v", src, dst, err)
> }
> defer r.Close()
>
> w, err := os.Create(dst)
> if err != nil {
> return fmt.Errorf("copy %s %s: %v", src, dst, err)
> }
>
> if _, err := io.Copy(w, r); err != nil {
> w.Close()
> os.Remove(dst)
> return fmt.Errorf("copy %s %s: %v", src, dst, err)
> }
>
> if err := w.Close(); err != nil {
> os.Remove(dst)
> return fmt.Errorf("copy %s %s: %v", src, dst, err)
> }
> }
>
> I think it is a bad example, how do you know where CopyFile failed?
>
> The "copy ..." part shouldn't be in there, you should add valuable context 
> to your errors, if CopyFile fails, the caller already knows it was a copy 
> error because the function has a big "Copy" on his name right? you should 
> do this instead:
>
> func CopyFile(dst, src string) error {
>   r, errOS := os.Open(src) // Avoid shadowing errors, don't use err
>   if errOS != nil {
> return fmt.Errorf("cannot open source: %v", errOS)
>   }
>
>   defer r.Close()
>
>   w, errCD := os.Create(dst)
>   if errCD != nil {
> return fmt.Errorf("cannot create destination: %v", errCD)
>   }
>
>   defer w.Close()
>
>   if _, err := io.Copy(w, r); err != nil { // Local scope error, so err is 
> fine
> os.Remove(dst)
> return fmt.Errorf("cannot copy data from source: %v", err)
>
>   }
>
>   if err := w.Close(); err != nil {
> os.Remove(dst)
> return fmt.Errorf("cannot close destination", err)
>   }
> }
>
> // Caller should do this.
> if err := CopyFile("dst.txt", "src.txt"); err != nil {
>   // Here is where you should add 'copy' to the error message.
>   return fmt.Errorf("cannot copy '%s' to '%s': %v", src, dst, err)
> }
>
> People complaining about Go's error handling regularly don't handle 
> errors, they just throw them like exceptions.
>
> If you really hate Go's error handling, just use:
>
> func catch(err error) {
>   if err != nil {
> panic(err)
>   }
>
>   // And use recover somewhere
> }
>
> Which is a bad practice, but at least we (the people who like how Go 
> handle errors) can still handle our errors without any language change.
>
> On Tue, Aug 1, 2023, 13:06 DrGo  wrote:
>
>> Thanks. 
>> The keystroke saving is not the motivation. The aim is to reduce the code 
>> reader’s mental load. My approach allows for clearer code where the main 
>> program logic is not dwarfed by the error handling code while maintaining 
>> the explicitly of error handling and the possible error-induced 
>> interruption in program flow. It avoids creating new if scope when one is 
>> not desired and offers opportunities for further deduplication of error 
>> handling code although each error is still handled individually. Compare 
>> the following; which one would you prefer to read a lot of?
>>
>> - current approach; error handling to program logic ratio: 13:5 
>>
>> func CopyFile(src, dst string) error {
>> r, err := os.Open(src)
>> if err != nil {
>> return fmt.Errorf("copy %s %s: %v", src, dst, err)
>> }
>> defer r.Close()
>>
>> w, err := os.Create(dst)
>> if err != nil {
>> return fmt.Errorf("copy %s %s: %v", src, dst, err)
>> }
>>
>> if _, err := io.Copy(w, r); err != nil {
>> w.Close()
>> os.Remove(dst)
>> return fmt.Errorf("copy %s %s: %v", src, dst, err)
>> }
>>
>> if err := w.Close(); err != nil {
>> os.Remove(dst)
>> return fmt.Errorf("copy %s %s: %v", src, dst, err)
>> }
>> }
>>
>> - new approach ratio 5:5
>> func CopyFile(src, dst string) error {
>> r, err := os.Open(src) *orelse* return fmt.Errorf("copy %s %s: %v", src, 
>> dst, err)
>> defer r.Close()
>>
>> w, err := os.Create(dst); *orelse* return fmt.Errorf("copy %s %s: %v", 
>> src, dst, err)
>> err := io.Copy(w, r) 

Re: [go-nuts] Re: Error handling

2023-08-04 Thread DrGo
Thanks Miguel and I am not offended.. It sounds you like the proposal and 
your comments were not about the proposal per se but about the cultural 
issues surrounding change and fear of unnecessary growth; here we agree too.


On Friday, August 4, 2023 at 6:47:37 AM UTC-6 Miguel Angel Rivera 
Notararigo wrote:

>
>
> On Thu, Aug 3, 2023, 23:45 DrGo  wrote:
>
>> @Miguel Angel Rivera Notararigo
>>
>> Thanks for taking the time to write... 
>>
>> In my proposal, people are free to add as much context as they want...
>>
>
> Yeah I know, I like your proposal, it is just how they handle errors in 
> the V programming language, although they use the keyword "or" and have 
> Options/Results. 
>
> but as a demonstration, I am using the example from 
>> Ross Cox's paper on error handling that is used by all error handling 
>> proposals to show case their approach. I do not think Ross will 
>> take your criticism personally :) 
>>
>
> I know, but just because he wrote that, doesn't mean it is the perfect 
> example. If I find myself writing code like that, I would probably hate 
> Go's error handling too, but that might be said for any other feature of 
> the language if I write some bad looking examples.
>
> I don't see how he could take my opinion personally, I didn't mean to be 
> rude, I just said it is a bad example. I am not a native speaker, so my 
> apologies if I wrote something rude.
>
> I on the other hand take exception to your generalization re people who 
>> complain about error handling in Go.
>> I am sure you did not make that claim without having some sort of solid 
>> research to support it. But, Go designers themselves admit that this is an 
>> issue and have written
>> tons on it.
>>
>
> You don't need a research or statistics if the complain is: "I don't want 
> to write 'if err != nil { return err }' every single time".
>
> It means they use "if err := w.Close(); err != nil { return err }" for 
> throwing the error, right? It is literally what they said or am I assuming?
>
> This same people will complain about your proposal, "I don't want to write 
> 'orelse return err' every single time", and then we will add 'w.Close()!' 
> or 'try w.Close()' to the language, and then we will be very happy with our 
> Go++ wich has 3 ways of doing the same thing.
>
>
>> In one or two replies above we were discussing how error handling 
>> opinions can become religions each with its own priests who think they are 
>> the only saved faction, and that their rituals are the only right approach 
>> for all situations.
>>
>
> I know, as I said, I like your proposal, but one of Go best features is 
> the lack of new features. I am arguing against my own taste, because I like 
> 'w.Close() or return fmt.Errorf("cannot close destination: %v", err)', but 
> I like more the simplicity of Go.
>
>
>> Best wishes,
>>
>>
>> On Thursday, August 3, 2023 at 9:07:52 PM UTC-6 Miguel Angel Rivera 
>> Notararigo wrote:
>>
>> func CopyFile(src, dst string) error {
>> r, err := os.Open(src)
>> if err != nil {
>> return fmt.Errorf("copy %s %s: %v", src, dst, err)
>> }
>> defer r.Close()
>>
>> w, err := os.Create(dst)
>> if err != nil {
>> return fmt.Errorf("copy %s %s: %v", src, dst, err)
>> }
>>
>> if _, err := io.Copy(w, r); err != nil {
>> w.Close()
>> os.Remove(dst)
>> return fmt.Errorf("copy %s %s: %v", src, dst, err)
>> }
>>
>> if err := w.Close(); err != nil {
>> os.Remove(dst)
>> return fmt.Errorf("copy %s %s: %v", src, dst, err)
>> }
>> }
>>
>> I think it is a bad example, how do you know where CopyFile failed?
>>
>> The "copy ..." part shouldn't be in there, you should add valuable 
>> context to your errors, if CopyFile fails, the caller already knows it was 
>> a copy error because the function has a big "Copy" on his name right? you 
>> should do this instead:
>>
>> func CopyFile(dst, src string) error {
>>   r, errOS := os.Open(src) // Avoid shadowing errors, don't use err
>>   if errOS != nil {
>> return fmt.Errorf("cannot open source: %v", errOS)
>>   }
>>
>>   defer r.Close()
>>
>>   w, errCD := os.Create(dst)
>>   if errCD != nil {
>> return fmt.Errorf("cannot create destination: %v", errCD)
>>   }
>>
>>   defer w.Close()
>>
>>   if _, err := io.Copy(w, r); err != nil { // Local scope error, so err 
>> is fine
>> os.Remove(dst)
>> return fmt.Errorf("cannot copy data from source: %v", err)
>>
>>   }
>>
>>   if err := w.Close(); err != nil {
>> os.Remove(dst)
>> return fmt.Errorf("cannot close destination", err)
>>   }
>> }
>>
>> // Caller should do this.
>> if err := CopyFile("dst.txt", "src.txt"); err != nil {
>>   // Here is where you should add 'copy' to the error message.
>>   return fmt.Errorf("cannot copy '%s' to '%s': %v", src, dst, err)
>> }
>>
>> People complaining about Go's error handling regularly don't handle 
>> errors, they just throw them like exceptions.
>>
>> If you really hate Go's error handling, just use:
>>
>> func catch(err error) {
>>   if err != nil {
>> 

Re: [go-nuts] Re: Error handling

2023-08-04 Thread Victor Giordano
Ok, that is a point to have in mind.

El vie, 4 ago 2023 a las 10:37, Miguel Angel Rivera Notararigo (<
ntr...@gmail.com>) escribió:

> I understand, but there is a little difference, you can find code out
> there improving performance thanks to generics, I am not sure if we can get
> any performance improvement by using "orelse return err".
>
>>

-- 
V

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/CAPUu9stVcB2wBqAAK1M72Axy9xa4Zvo8uP59MOgOoCQtFNZNDw%40mail.gmail.com.


Re: [go-nuts] Re: Error handling

2023-08-04 Thread Miguel Angel Rivera Notararigo
I understand, but there is a little difference, you can find code out there
improving performance thanks to generics, I am not sure if we can get any
performance improvement by using "orelse return err".

>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/CAF9DLCkBtF37j0tKpu%2BWoHBhEfE5iQ7ygWw0eDVg-HcAUzUsCA%40mail.gmail.com.


Re: [go-nuts] Re: Error handling

2023-08-04 Thread Victor Giordano
> Generics add a lot of value

>From a personal point of view with the interfaces I got all the genericity
I needed to model solutions, and generics per se doesn't provide a new
approach to find solutions.
I Mean, you can solve the same old problems with or without generics...
Generics provides another way of writing code, just as this proposal to
deal with errors. This is my view on this matter.



El vie, 4 ago 2023 a las 10:16, Miguel Angel Rivera Notararigo (<
ntr...@gmail.com>) escribió:

> It is not just resistance to change, it is about not adding new features
> that add more complexity than value. I am pretty sure people will complain
> about Go's error handling even if we use "orelse return err".
>
> Generics add a lot of value, it shows the Go team is open to changes. But
> imagine they add any feature people ask, C++ would be simpler than Go.
>
> As I said, I like the proposal, but I have learned that some times, I have
> to accept things are not always as I want them to be.
>
> On Fri, Aug 4, 2023, 08:58 Victor Giordano  wrote:
>
>> As far as I see things there is always room for changes... but changes
>> doesn't come without some resistance.. That is natural...
>>
>> >  Go best features is the lack of new features.
>>
>> What about generics? That was a major change... It was really necessary
>> or not is another topic.
>>
>> El vie, 4 ago 2023 a las 9:47, Miguel Angel Rivera Notararigo (<
>> ntr...@gmail.com>) escribió:
>>
>>>
>>>
>>> On Thu, Aug 3, 2023, 23:45 DrGo  wrote:
>>>
 @Miguel Angel Rivera Notararigo

 Thanks for taking the time to write...

 In my proposal, people are free to add as much context as they want...

>>>
>>> Yeah I know, I like your proposal, it is just how they handle errors in
>>> the V programming language, although they use the keyword "or" and have
>>> Options/Results.
>>>
>>> but as a demonstration, I am using the example from
 Ross Cox's paper on error handling that is used by all error handling
 proposals to show case their approach. I do not think Ross will
 take your criticism personally :)

>>>
>>> I know, but just because he wrote that, doesn't mean it is the perfect
>>> example. If I find myself writing code like that, I would probably hate
>>> Go's error handling too, but that might be said for any other feature of
>>> the language if I write some bad looking examples.
>>>
>>> I don't see how he could take my opinion personally, I didn't mean to be
>>> rude, I just said it is a bad example. I am not a native speaker, so my
>>> apologies if I wrote something rude.
>>>
>>> I on the other hand take exception to your generalization re people who
 complain about error handling in Go.
 I am sure you did not make that claim without having some sort of solid
 research to support it. But, Go designers themselves admit that this is an
 issue and have written
 tons on it.

>>>
>>> You don't need a research or statistics if the complain is: "I don't
>>> want to write 'if err != nil { return err }' every single time".
>>>
>>> It means they use "if err := w.Close(); err != nil { return err }" for
>>> throwing the error, right? It is literally what they said or am I assuming?
>>>
>>> This same people will complain about your proposal, "I don't want to
>>> write 'orelse return err' every single time", and then we will add
>>> 'w.Close()!' or 'try w.Close()' to the language, and then we will be very
>>> happy with our Go++ wich has 3 ways of doing the same thing.
>>>
>>>
 In one or two replies above we were discussing how error handling
 opinions can become religions each with its own priests who think they are
 the only saved faction, and that their rituals are the only right approach
 for all situations.

>>>
>>> I know, as I said, I like your proposal, but one of Go best features is
>>> the lack of new features. I am arguing against my own taste, because I like
>>> 'w.Close() or return fmt.Errorf("cannot close destination: %v", err)', but
>>> I like more the simplicity of Go.
>>>
>>>
 Best wishes,


 On Thursday, August 3, 2023 at 9:07:52 PM UTC-6 Miguel Angel Rivera
 Notararigo wrote:

 func CopyFile(src, dst string) error {
 r, err := os.Open(src)
 if err != nil {
 return fmt.Errorf("copy %s %s: %v", src, dst, err)
 }
 defer r.Close()

 w, err := os.Create(dst)
 if err != nil {
 return fmt.Errorf("copy %s %s: %v", src, dst, err)
 }

 if _, err := io.Copy(w, r); err != nil {
 w.Close()
 os.Remove(dst)
 return fmt.Errorf("copy %s %s: %v", src, dst, err)
 }

 if err := w.Close(); err != nil {
 os.Remove(dst)
 return fmt.Errorf("copy %s %s: %v", src, dst, err)
 }
 }

 I think it is a bad example, how do you know where CopyFile failed?

 The "copy ..." part shouldn't be in there, you should add valuable
 context to your errors, if CopyFile fails, the caller 

Re: [go-nuts] Re: Error handling

2023-08-04 Thread Miguel Angel Rivera Notararigo
It is not just resistance to change, it is about not adding new features
that add more complexity than value. I am pretty sure people will complain
about Go's error handling even if we use "orelse return err".

Generics add a lot of value, it shows the Go team is open to changes. But
imagine they add any feature people ask, C++ would be simpler than Go.

As I said, I like the proposal, but I have learned that some times, I have
to accept things are not always as I want them to be.

On Fri, Aug 4, 2023, 08:58 Victor Giordano  wrote:

> As far as I see things there is always room for changes... but changes
> doesn't come without some resistance.. That is natural...
>
> >  Go best features is the lack of new features.
>
> What about generics? That was a major change... It was really necessary or
> not is another topic.
>
> El vie, 4 ago 2023 a las 9:47, Miguel Angel Rivera Notararigo (<
> ntr...@gmail.com>) escribió:
>
>>
>>
>> On Thu, Aug 3, 2023, 23:45 DrGo  wrote:
>>
>>> @Miguel Angel Rivera Notararigo
>>>
>>> Thanks for taking the time to write...
>>>
>>> In my proposal, people are free to add as much context as they want...
>>>
>>
>> Yeah I know, I like your proposal, it is just how they handle errors in
>> the V programming language, although they use the keyword "or" and have
>> Options/Results.
>>
>> but as a demonstration, I am using the example from
>>> Ross Cox's paper on error handling that is used by all error handling
>>> proposals to show case their approach. I do not think Ross will
>>> take your criticism personally :)
>>>
>>
>> I know, but just because he wrote that, doesn't mean it is the perfect
>> example. If I find myself writing code like that, I would probably hate
>> Go's error handling too, but that might be said for any other feature of
>> the language if I write some bad looking examples.
>>
>> I don't see how he could take my opinion personally, I didn't mean to be
>> rude, I just said it is a bad example. I am not a native speaker, so my
>> apologies if I wrote something rude.
>>
>> I on the other hand take exception to your generalization re people who
>>> complain about error handling in Go.
>>> I am sure you did not make that claim without having some sort of solid
>>> research to support it. But, Go designers themselves admit that this is an
>>> issue and have written
>>> tons on it.
>>>
>>
>> You don't need a research or statistics if the complain is: "I don't want
>> to write 'if err != nil { return err }' every single time".
>>
>> It means they use "if err := w.Close(); err != nil { return err }" for
>> throwing the error, right? It is literally what they said or am I assuming?
>>
>> This same people will complain about your proposal, "I don't want to
>> write 'orelse return err' every single time", and then we will add
>> 'w.Close()!' or 'try w.Close()' to the language, and then we will be very
>> happy with our Go++ wich has 3 ways of doing the same thing.
>>
>>
>>> In one or two replies above we were discussing how error handling
>>> opinions can become religions each with its own priests who think they are
>>> the only saved faction, and that their rituals are the only right approach
>>> for all situations.
>>>
>>
>> I know, as I said, I like your proposal, but one of Go best features is
>> the lack of new features. I am arguing against my own taste, because I like
>> 'w.Close() or return fmt.Errorf("cannot close destination: %v", err)', but
>> I like more the simplicity of Go.
>>
>>
>>> Best wishes,
>>>
>>>
>>> On Thursday, August 3, 2023 at 9:07:52 PM UTC-6 Miguel Angel Rivera
>>> Notararigo wrote:
>>>
>>> func CopyFile(src, dst string) error {
>>> r, err := os.Open(src)
>>> if err != nil {
>>> return fmt.Errorf("copy %s %s: %v", src, dst, err)
>>> }
>>> defer r.Close()
>>>
>>> w, err := os.Create(dst)
>>> if err != nil {
>>> return fmt.Errorf("copy %s %s: %v", src, dst, err)
>>> }
>>>
>>> if _, err := io.Copy(w, r); err != nil {
>>> w.Close()
>>> os.Remove(dst)
>>> return fmt.Errorf("copy %s %s: %v", src, dst, err)
>>> }
>>>
>>> if err := w.Close(); err != nil {
>>> os.Remove(dst)
>>> return fmt.Errorf("copy %s %s: %v", src, dst, err)
>>> }
>>> }
>>>
>>> I think it is a bad example, how do you know where CopyFile failed?
>>>
>>> The "copy ..." part shouldn't be in there, you should add valuable
>>> context to your errors, if CopyFile fails, the caller already knows it was
>>> a copy error because the function has a big "Copy" on his name right? you
>>> should do this instead:
>>>
>>> func CopyFile(dst, src string) error {
>>>   r, errOS := os.Open(src) // Avoid shadowing errors, don't use err
>>>   if errOS != nil {
>>> return fmt.Errorf("cannot open source: %v", errOS)
>>>   }
>>>
>>>   defer r.Close()
>>>
>>>   w, errCD := os.Create(dst)
>>>   if errCD != nil {
>>> return fmt.Errorf("cannot create destination: %v", errCD)
>>>   }
>>>
>>>   defer w.Close()
>>>
>>>   if _, err := io.Copy(w, r); err != nil { // Local scope error, so err
>>> is fine
>>> 

Re: [go-nuts] Re: Error handling

2023-08-04 Thread Victor Giordano
As far as I see things there is always room for changes... but changes
doesn't come without some resistance.. That is natural...

>  Go best features is the lack of new features.

What about generics? That was a major change... It was really necessary or
not is another topic.

El vie, 4 ago 2023 a las 9:47, Miguel Angel Rivera Notararigo (<
ntr...@gmail.com>) escribió:

>
>
> On Thu, Aug 3, 2023, 23:45 DrGo  wrote:
>
>> @Miguel Angel Rivera Notararigo
>>
>> Thanks for taking the time to write...
>>
>> In my proposal, people are free to add as much context as they want...
>>
>
> Yeah I know, I like your proposal, it is just how they handle errors in
> the V programming language, although they use the keyword "or" and have
> Options/Results.
>
> but as a demonstration, I am using the example from
>> Ross Cox's paper on error handling that is used by all error handling
>> proposals to show case their approach. I do not think Ross will
>> take your criticism personally :)
>>
>
> I know, but just because he wrote that, doesn't mean it is the perfect
> example. If I find myself writing code like that, I would probably hate
> Go's error handling too, but that might be said for any other feature of
> the language if I write some bad looking examples.
>
> I don't see how he could take my opinion personally, I didn't mean to be
> rude, I just said it is a bad example. I am not a native speaker, so my
> apologies if I wrote something rude.
>
> I on the other hand take exception to your generalization re people who
>> complain about error handling in Go.
>> I am sure you did not make that claim without having some sort of solid
>> research to support it. But, Go designers themselves admit that this is an
>> issue and have written
>> tons on it.
>>
>
> You don't need a research or statistics if the complain is: "I don't want
> to write 'if err != nil { return err }' every single time".
>
> It means they use "if err := w.Close(); err != nil { return err }" for
> throwing the error, right? It is literally what they said or am I assuming?
>
> This same people will complain about your proposal, "I don't want to write
> 'orelse return err' every single time", and then we will add 'w.Close()!'
> or 'try w.Close()' to the language, and then we will be very happy with our
> Go++ wich has 3 ways of doing the same thing.
>
>
>> In one or two replies above we were discussing how error handling
>> opinions can become religions each with its own priests who think they are
>> the only saved faction, and that their rituals are the only right approach
>> for all situations.
>>
>
> I know, as I said, I like your proposal, but one of Go best features is
> the lack of new features. I am arguing against my own taste, because I like
> 'w.Close() or return fmt.Errorf("cannot close destination: %v", err)', but
> I like more the simplicity of Go.
>
>
>> Best wishes,
>>
>>
>> On Thursday, August 3, 2023 at 9:07:52 PM UTC-6 Miguel Angel Rivera
>> Notararigo wrote:
>>
>> func CopyFile(src, dst string) error {
>> r, err := os.Open(src)
>> if err != nil {
>> return fmt.Errorf("copy %s %s: %v", src, dst, err)
>> }
>> defer r.Close()
>>
>> w, err := os.Create(dst)
>> if err != nil {
>> return fmt.Errorf("copy %s %s: %v", src, dst, err)
>> }
>>
>> if _, err := io.Copy(w, r); err != nil {
>> w.Close()
>> os.Remove(dst)
>> return fmt.Errorf("copy %s %s: %v", src, dst, err)
>> }
>>
>> if err := w.Close(); err != nil {
>> os.Remove(dst)
>> return fmt.Errorf("copy %s %s: %v", src, dst, err)
>> }
>> }
>>
>> I think it is a bad example, how do you know where CopyFile failed?
>>
>> The "copy ..." part shouldn't be in there, you should add valuable
>> context to your errors, if CopyFile fails, the caller already knows it was
>> a copy error because the function has a big "Copy" on his name right? you
>> should do this instead:
>>
>> func CopyFile(dst, src string) error {
>>   r, errOS := os.Open(src) // Avoid shadowing errors, don't use err
>>   if errOS != nil {
>> return fmt.Errorf("cannot open source: %v", errOS)
>>   }
>>
>>   defer r.Close()
>>
>>   w, errCD := os.Create(dst)
>>   if errCD != nil {
>> return fmt.Errorf("cannot create destination: %v", errCD)
>>   }
>>
>>   defer w.Close()
>>
>>   if _, err := io.Copy(w, r); err != nil { // Local scope error, so err
>> is fine
>> os.Remove(dst)
>> return fmt.Errorf("cannot copy data from source: %v", err)
>>
>>   }
>>
>>   if err := w.Close(); err != nil {
>> os.Remove(dst)
>> return fmt.Errorf("cannot close destination", err)
>>   }
>> }
>>
>> // Caller should do this.
>> if err := CopyFile("dst.txt", "src.txt"); err != nil {
>>   // Here is where you should add 'copy' to the error message.
>>   return fmt.Errorf("cannot copy '%s' to '%s': %v", src, dst, err)
>> }
>>
>> People complaining about Go's error handling regularly don't handle
>> errors, they just throw them like exceptions.
>>
>> If you really hate Go's error handling, just use:
>>
>> func catch(err error) {
>>   if 

Re: [go-nuts] Re: Error handling

2023-08-04 Thread Miguel Angel Rivera Notararigo
On Thu, Aug 3, 2023, 23:45 DrGo  wrote:

> @Miguel Angel Rivera Notararigo
>
> Thanks for taking the time to write...
>
> In my proposal, people are free to add as much context as they want...
>

Yeah I know, I like your proposal, it is just how they handle errors in the
V programming language, although they use the keyword "or" and have
Options/Results.

but as a demonstration, I am using the example from
> Ross Cox's paper on error handling that is used by all error handling
> proposals to show case their approach. I do not think Ross will
> take your criticism personally :)
>

I know, but just because he wrote that, doesn't mean it is the perfect
example. If I find myself writing code like that, I would probably hate
Go's error handling too, but that might be said for any other feature of
the language if I write some bad looking examples.

I don't see how he could take my opinion personally, I didn't mean to be
rude, I just said it is a bad example. I am not a native speaker, so my
apologies if I wrote something rude.

I on the other hand take exception to your generalization re people who
> complain about error handling in Go.
> I am sure you did not make that claim without having some sort of solid
> research to support it. But, Go designers themselves admit that this is an
> issue and have written
> tons on it.
>

You don't need a research or statistics if the complain is: "I don't want
to write 'if err != nil { return err }' every single time".

It means they use "if err := w.Close(); err != nil { return err }" for
throwing the error, right? It is literally what they said or am I assuming?

This same people will complain about your proposal, "I don't want to write
'orelse return err' every single time", and then we will add 'w.Close()!'
or 'try w.Close()' to the language, and then we will be very happy with our
Go++ wich has 3 ways of doing the same thing.


> In one or two replies above we were discussing how error handling opinions
> can become religions each with its own priests who think they are the only
> saved faction, and that their rituals are the only right approach for all
> situations.
>

I know, as I said, I like your proposal, but one of Go best features is the
lack of new features. I am arguing against my own taste, because I like
'w.Close() or return fmt.Errorf("cannot close destination: %v", err)', but
I like more the simplicity of Go.


> Best wishes,
>
>
> On Thursday, August 3, 2023 at 9:07:52 PM UTC-6 Miguel Angel Rivera
> Notararigo wrote:
>
> func CopyFile(src, dst string) error {
> r, err := os.Open(src)
> if err != nil {
> return fmt.Errorf("copy %s %s: %v", src, dst, err)
> }
> defer r.Close()
>
> w, err := os.Create(dst)
> if err != nil {
> return fmt.Errorf("copy %s %s: %v", src, dst, err)
> }
>
> if _, err := io.Copy(w, r); err != nil {
> w.Close()
> os.Remove(dst)
> return fmt.Errorf("copy %s %s: %v", src, dst, err)
> }
>
> if err := w.Close(); err != nil {
> os.Remove(dst)
> return fmt.Errorf("copy %s %s: %v", src, dst, err)
> }
> }
>
> I think it is a bad example, how do you know where CopyFile failed?
>
> The "copy ..." part shouldn't be in there, you should add valuable context
> to your errors, if CopyFile fails, the caller already knows it was a copy
> error because the function has a big "Copy" on his name right? you should
> do this instead:
>
> func CopyFile(dst, src string) error {
>   r, errOS := os.Open(src) // Avoid shadowing errors, don't use err
>   if errOS != nil {
> return fmt.Errorf("cannot open source: %v", errOS)
>   }
>
>   defer r.Close()
>
>   w, errCD := os.Create(dst)
>   if errCD != nil {
> return fmt.Errorf("cannot create destination: %v", errCD)
>   }
>
>   defer w.Close()
>
>   if _, err := io.Copy(w, r); err != nil { // Local scope error, so err is
> fine
> os.Remove(dst)
> return fmt.Errorf("cannot copy data from source: %v", err)
>
>   }
>
>   if err := w.Close(); err != nil {
> os.Remove(dst)
> return fmt.Errorf("cannot close destination", err)
>   }
> }
>
> // Caller should do this.
> if err := CopyFile("dst.txt", "src.txt"); err != nil {
>   // Here is where you should add 'copy' to the error message.
>   return fmt.Errorf("cannot copy '%s' to '%s': %v", src, dst, err)
> }
>
> People complaining about Go's error handling regularly don't handle
> errors, they just throw them like exceptions.
>
> If you really hate Go's error handling, just use:
>
> func catch(err error) {
>   if err != nil {
> panic(err)
>   }
>
>   // And use recover somewhere
> }
>
> Which is a bad practice, but at least we (the people who like how Go
> handle errors) can still handle our errors without any language change.
>
> On Tue, Aug 1, 2023, 13:06 DrGo wrote:
>
> Thanks.
> The keystroke saving is not the motivation. The aim is to reduce the code
> reader’s mental load. My approach allows for clearer code where the main
> program logic is not dwarfed by the error handling code while maintaining
> the explicitly of error handling and 

Re: [go-nuts] Re: Error handling

2023-08-03 Thread DrGo
@Miguel Angel Rivera Notararigo

Thanks for taking the time to write... 

In my proposal, people are free to add as much context as they want... but 
as a demonstration, I am using the example from 
Ross Cox's paper on error handling that is used by all error handling 
proposals to show case their approach. I do not think Ross will 
take your criticism personally :) I on the other hand take exception to 
your generalization re people who complain about error handling in Go.
I am sure you did not make that claim without having some sort of solid 
research to support it. But, Go designers themselves admit that this is an 
issue and have written
tons on it.

In one or two replies above we were discussing how error handling opinions 
can become religions each with its own priests who think they are the only 
saved faction, and that their rituals are the only right approach for all 
situations.

Best wishes,


On Thursday, August 3, 2023 at 9:07:52 PM UTC-6 Miguel Angel Rivera 
Notararigo wrote:

func CopyFile(src, dst string) error {
r, err := os.Open(src)
if err != nil {
return fmt.Errorf("copy %s %s: %v", src, dst, err)
}
defer r.Close()

w, err := os.Create(dst)
if err != nil {
return fmt.Errorf("copy %s %s: %v", src, dst, err)
}

if _, err := io.Copy(w, r); err != nil {
w.Close()
os.Remove(dst)
return fmt.Errorf("copy %s %s: %v", src, dst, err)
}

if err := w.Close(); err != nil {
os.Remove(dst)
return fmt.Errorf("copy %s %s: %v", src, dst, err)
}
}

I think it is a bad example, how do you know where CopyFile failed?

The "copy ..." part shouldn't be in there, you should add valuable context 
to your errors, if CopyFile fails, the caller already knows it was a copy 
error because the function has a big "Copy" on his name right? you should 
do this instead:

func CopyFile(dst, src string) error {
  r, errOS := os.Open(src) // Avoid shadowing errors, don't use err
  if errOS != nil {
return fmt.Errorf("cannot open source: %v", errOS)
  }

  defer r.Close()

  w, errCD := os.Create(dst)
  if errCD != nil {
return fmt.Errorf("cannot create destination: %v", errCD)
  }

  defer w.Close()

  if _, err := io.Copy(w, r); err != nil { // Local scope error, so err is 
fine
os.Remove(dst)
return fmt.Errorf("cannot copy data from source: %v", err)

  }

  if err := w.Close(); err != nil {
os.Remove(dst)
return fmt.Errorf("cannot close destination", err)
  }
}

// Caller should do this.
if err := CopyFile("dst.txt", "src.txt"); err != nil {
  // Here is where you should add 'copy' to the error message.
  return fmt.Errorf("cannot copy '%s' to '%s': %v", src, dst, err)
}

People complaining about Go's error handling regularly don't handle errors, 
they just throw them like exceptions.

If you really hate Go's error handling, just use:

func catch(err error) {
  if err != nil {
panic(err)
  }

  // And use recover somewhere
}

Which is a bad practice, but at least we (the people who like how Go handle 
errors) can still handle our errors without any language change.

On Tue, Aug 1, 2023, 13:06 DrGo wrote:

Thanks. 
The keystroke saving is not the motivation. The aim is to reduce the code 
reader’s mental load. My approach allows for clearer code where the main 
program logic is not dwarfed by the error handling code while maintaining 
the explicitly of error handling and the possible error-induced 
interruption in program flow. It avoids creating new if scope when one is 
not desired and offers opportunities for further deduplication of error 
handling code although each error is still handled individually. Compare 
the following; which one would you prefer to read a lot of?

- current approach; error handling to program logic ratio: 13:5 

func CopyFile(src, dst string) error {
r, err := os.Open(src)
if err != nil {
return fmt.Errorf("copy %s %s: %v", src, dst, err)
}
defer r.Close()

w, err := os.Create(dst)
if err != nil {
return fmt.Errorf("copy %s %s: %v", src, dst, err)
}

if _, err := io.Copy(w, r); err != nil {
w.Close()
os.Remove(dst)
return fmt.Errorf("copy %s %s: %v", src, dst, err)
}

if err := w.Close(); err != nil {
os.Remove(dst)
return fmt.Errorf("copy %s %s: %v", src, dst, err)
}
}

- new approach ratio 5:5
func CopyFile(src, dst string) error {
r, err := os.Open(src) *orelse* return fmt.Errorf("copy %s %s: %v", src, 
dst, err)
defer r.Close()

w, err := os.Create(dst); *orelse* return fmt.Errorf("copy %s %s: %v", src, 
dst, err)
err := io.Copy(w, r) *orelse* {
w.Close()
os.Remove(dst)
return fmt.Errorf("copy %s %s: %v", src, dst, err)
}

err := w.Close() *orelse* {
os.Remove(dst)
return fmt.Errorf("copy %s %s: %v", src, dst, err)
}
}

On Sunday, July 30, 2023 at 9:27:27 PM UTC-6 Marcello H wrote:

I think the current error handling is just fine.
For the extra typing, they invented keyboard snippets and such.

But for this proposal, I would like to see how a return with multiple 
values would look to get a better understanding.
```
// translate this in the proposed solution?

Re: [go-nuts] Re: Error handling

2023-08-03 Thread Miguel Angel Rivera Notararigo
func CopyFile(src, dst string) error {
r, err := os.Open(src)
if err != nil {
return fmt.Errorf("copy %s %s: %v", src, dst, err)
}
defer r.Close()

w, err := os.Create(dst)
if err != nil {
return fmt.Errorf("copy %s %s: %v", src, dst, err)
}

if _, err := io.Copy(w, r); err != nil {
w.Close()
os.Remove(dst)
return fmt.Errorf("copy %s %s: %v", src, dst, err)
}

if err := w.Close(); err != nil {
os.Remove(dst)
return fmt.Errorf("copy %s %s: %v", src, dst, err)
}
}

I think it is a bad example, how do you know where CopyFile failed?

The "copy ..." part shouldn't be in there, you should add valuable context
to your errors, if CopyFile fails, the caller already knows it was a copy
error because the function has a big "Copy" on his name right? you should
do this instead:

func CopyFile(dst, src string) error {
  r, errOS := os.Open(src) // Avoid shadowing errors, don't use err
  if errOS != nil {
return fmt.Errorf("cannot open source: %v", errOS)
  }

  defer r.Close()

  w, errCD := os.Create(dst)
  if errCD != nil {
return fmt.Errorf("cannot create destination: %v", errCD)
  }

  defer w.Close()

  if _, err := io.Copy(w, r); err != nil { // Local scope error, so err is
fine
os.Remove(dst)
return fmt.Errorf("cannot copy data from source: %v", err)
  }

  if err := w.Close(); err != nil {
os.Remove(dst)
return fmt.Errorf("cannot close destination", err)
  }
}

// Caller should do this.
if err := CopyFile("dst.txt", "src.txt"); err != nil {
  // Here is where you should add 'copy' to the error message.
  return fmt.Errorf("cannot copy '%s' to '%s': %v", src, dst, err)
}

People complaining about Go's error handling regularly don't handle errors,
they just throw them like exceptions.

If you really hate Go's error handling, just use:

func catch(err error) {
  if err != nil {
panic(err)
  }

  // And use recover somewhere
}

Which is a bad practice, but at least we (the people who like how Go handle
errors) can still handle our errors without any language change.

On Tue, Aug 1, 2023, 13:06 DrGo  wrote:

> Thanks.
> The keystroke saving is not the motivation. The aim is to reduce the code
> reader’s mental load. My approach allows for clearer code where the main
> program logic is not dwarfed by the error handling code while maintaining
> the explicitly of error handling and the possible error-induced
> interruption in program flow. It avoids creating new if scope when one is
> not desired and offers opportunities for further deduplication of error
> handling code although each error is still handled individually. Compare
> the following; which one would you prefer to read a lot of?
>
> - current approach; error handling to program logic ratio: 13:5
>
> func CopyFile(src, dst string) error {
> r, err := os.Open(src)
> if err != nil {
> return fmt.Errorf("copy %s %s: %v", src, dst, err)
> }
> defer r.Close()
>
> w, err := os.Create(dst)
> if err != nil {
> return fmt.Errorf("copy %s %s: %v", src, dst, err)
> }
>
> if _, err := io.Copy(w, r); err != nil {
> w.Close()
> os.Remove(dst)
> return fmt.Errorf("copy %s %s: %v", src, dst, err)
> }
>
> if err := w.Close(); err != nil {
> os.Remove(dst)
> return fmt.Errorf("copy %s %s: %v", src, dst, err)
> }
> }
>
> - new approach ratio 5:5
> func CopyFile(src, dst string) error {
> r, err := os.Open(src) *orelse* return fmt.Errorf("copy %s %s: %v", src,
> dst, err)
> defer r.Close()
>
> w, err := os.Create(dst); *orelse* return fmt.Errorf("copy %s %s: %v",
> src, dst, err)
> err := io.Copy(w, r) *orelse* {
> w.Close()
> os.Remove(dst)
> return fmt.Errorf("copy %s %s: %v", src, dst, err)
> }
>
> err := w.Close() *orelse* {
> os.Remove(dst)
> return fmt.Errorf("copy %s %s: %v", src, dst, err)
> }
> }
>
> On Sunday, July 30, 2023 at 9:27:27 PM UTC-6 Marcello H wrote:
>
>> I think the current error handling is just fine.
>> For the extra typing, they invented keyboard snippets and such.
>>
>> But for this proposal, I would like to see how a return with multiple
>> values would look to get a better understanding.
>> ```
>> // translate this in the proposed solution?
>> func myFirstFunction() (string, err) {
>>result, err := myFunction()
>>if err != nill {
>>return rest, err
>>}
>> }
>> ```
>>
>> Op maandag 31 juli 2023 om 04:32:01 UTC+2 schreef DrGo:
>>
>>> Another possibility Jeremy is that the orelse block is executed if any
>>> of the returned error values is not nil.
>>>
>>> On Sunday, July 30, 2023 at 8:14:58 PM UTC-6 DrGo wrote:
>>>
 Thanks...
 yes indeed. Too many requirements but I think this solution comes close
 to meeting them. If a rare function returns more than one error value (yet
 to see one in the wild) then the compiler should reject orelse use and the
 user can fallback on the (the if err!= nil) approach.

 On Sunday, July 30, 2023 at 6:02:57 PM UTC-6 Jeremy French wrote:

> Also, errors are values, which means - although uncommon - a function
> could return two or more 

[go-nuts] Re: Error handling

2023-08-01 Thread Stephen Illingworth
On Tuesday, 1 August 2023 at 18:14:56 UTC+1 DrGo wrote:

Fair enough. But many would prefer shorter functions if there is no loss to 
explicitness or clarity. 


I don't think putting the assignment and return statement on the same line 
is very clear. I would prefer
the compiler to enforce something like the following:

func CopyFile(src, dst string) error {
r, err := os.Open(src) *orelse* {
return fmt.Errorf("copy %s %s: %v", src, dst, err)
}
defer r.Close()

w, err := os.Create(dst) *orelse* {
return fmt.Errorf("copy %s %s: %v", src, dst, err)
}
err := io.Copy(w, r) *orelse* {
w.Close()
os.Remove(dst)
return fmt.Errorf("copy %s %s: %v", src, dst, err)
}

err := w.Close() *orelse* {
os.Remove(dst)
return fmt.Errorf("copy %s %s: %v", src, dst, err)
}
}

What do you intend to happen to the error instances after the orelse block? 
Are they valid outside the orelse block?


-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/6dd26b81-23b3-4226-9eb9-3bc47b2bee54n%40googlegroups.com.


[go-nuts] Re: Error handling

2023-08-01 Thread DrGo
Fair enough. But many would prefer shorter functions if there is no loss to 
explicitness or clarity. 

On Tuesday, August 1, 2023 at 11:10:30 AM UTC-6 Stephen Illingworth wrote:

> On Tuesday, 1 August 2023 at 18:06:25 UTC+1 DrGo wrote:
>
> Compare the following; which one would you prefer to read a lot of?
>
>
> You've asked a fair question so you deserve an honest answer. Looking at 
> the two examples, I would prefer to read the code in the first example.
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/807cc6b3-49d8-43b1-b35f-ba711c82822cn%40googlegroups.com.


Re: [go-nuts] Re: Error handling

2023-08-01 Thread DrGo
Thanks Jan
Indeed the majority can be wrong but in this case the OLD smart minority 
too wanted a way to improve things. This approach was in fact dictated by 
their requirements 

On Tuesday, August 1, 2023 at 2:10:57 AM UTC-6 Jan Mercl wrote:

> On Tue, Aug 1, 2023 at 1:47 AM DrGo  wrote:
>
> > The verbosity of error handling is the number one concern for Go 
> developers in the most recent survey.
>
> That says something about those developers, about their preferences,
> opinions, taste etc and that it differs from what the Original
> Language Designers (OLD™) preferred.
>
> It has close to zero bits of information which preferences are the
> better ones. It's a subjective category anyway.
>
> > So there is a need for doing something about it..
>
> And here's IMO the mistake. You may feel the need, Joe and Mary may
> not. It's ok to have preferences. It's ok for preferences to be
> different. It does not mean there's a need to change anything. Of
> course, you can decide that following the preferences of a majority of
> developers is a rational move.
>
> I claim it a fallacy. A big one. Let me not joke about billion flies,
> but the fact is - language designers are few and far between while
> developers come in heaps. And let's be honest. Most developers write
> horrible code, me included. Maybe you're the rare exception, congrats
> then. But the majority of us are just the ordinary, average coders for
> hire. There are deadlines to meet, bills to pay, project mis-managers
> getting into the way etc. We have all experienced that, didn't we?
>
> I, for one learned to pay much more attention to what language
> designers do and say. Sometimes I agree, sometime I don't. But I
> believe one can, in essence, ignore what the majority of developers
> thinks about it. Actually, I think the majority of developers is wrong
> more often than the, most of the time silent, minority.
>
> -j
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/bdee0b89-2098-4c32-b6a5-8cb3aa54abccn%40googlegroups.com.


Re: [go-nuts] Re: Error handling

2023-08-01 Thread DrGo

Thanks Tim for patiently explaining your perspective. Much appreciated. 
Please see my reply to Marcelo H showing using real life code  that the 
outcome goes much further than replacing the err!=  nil bit. 
On Monday, July 31, 2023 at 7:20:18 PM UTC-6 Tim Casey wrote:

>
> >> You do not think this is a significant  reduction in boilerplate?
>
> I understand people having a complaint about the verbosity of error 
> handling.  But, this follows C code error handling.  So to me, it is not 
> all *that* bad.  
> I think the measurable reduction in boilerplate code is ' ; err != nil' 
> for ' orelse '.   And I do not believe this is worth a keyword.  Some of 
> the context is  being used to C.  And another aspect is being used to perl 
> and its one liners.  With perl, the debugger is not something which is 
> close to gdb/adb or the like.  So the comparison is not about saving code.
>
> I would suggest, if I had a bold idea (and probably dumb), to have a 
> functional way to handle this.   Something like:
>
> HandleErrorChain( todoList []func() (TYPE,error), errorHandler func () 
> TYPE, error ) (TYPE, error)
>
> Which means, I have a list of things I want to do and I want the error 
> handling to be all the same for all of them.  Then the *chain* of things 
> would make sense with a single handler.  This has the expense of being 
> kinda odd so at the very least it would need idiomatic polishing.  I also 
> think I am too ignorant to have a real say in any of this.
>
> >> Why it won't work with one time retires? That is like one time retires 
> won't work in an if-else block
>
> I think there is a bit of talking past each other here.  Or at least I 
> dont understand.  I think orelse is too specific to be helpful.  That is, 
> it is too precise to reduce a large swath of what might look like error 
> handling code, because error handling code can at times be specific.  The 
> first dumb example I came up with is a simple one-time retry, which I have 
> put in code at times.  It is usually ugly, but effective:
>
> v,err := dosomething()
> if err != nil {
> v,err = dosomething()
> }
> if err != nil {
> handleError(err)
>}
>importantOperation(v)
>
> This with the token:
>
> if v,err := dosomething() orelse {
> v,err = dosomething() orelse {
> handleError()
> }
> }
> importantOperation(v)
>
> The savings is the two 'err != nil' lines.
>
> If I take a step back, some of what I am reacting to is how much it is 
> discussed.  It *feels*, at least to me as an ignorant person in this 
> context, as if people were not handling errors previously.  Golang is 
> forcing this now and the resulting lines of code look like 'too much' 
> compared to previous lines of code.  But I think this is a direct design 
> goal.  If the keyword vs lines of code/tokenspace is worth it, so be it.  
> Who am I to say.  If we are truely circling on a way to handle errors in a 
> chain, then the chain aspect is at least as important as any one line, and 
> up to this point has largely been ignored.
>
> In any event, i dont mean to be argumentative or even contrarian.  Sorry 
> if it comes across that way.
>
> tim
>
>
> On Mon, Jul 31, 2023 at 4:46 PM DrGo  wrote:
>
>> Thanks for the valuable feedback,
>> The verbosity of error handling is the number one concern for Go 
>> developers in the most recent survey. So there is a need for doing 
>> something about it.. except that there are many possibly conflicting 
>> requirements outlined by the Go team. 
>> The problem with the abbreviated if err!= nil in your example:
>>   if x,err := something() ; err != nil {
>> handleErrorAndReturn
>> }
>> is that x is local to the if scope and often that won't work forcing the 
>> more verbose:
>>x,err := something()
>>   if err != nil {
>> handleErrorAndReturn
>> } 
>> If you have few of those as is the case in io programs; there is real 
>> impact on the readability of the code.
>> the oresle approach avoids that problem (the x stays in the scope of the 
>> func).
>>
>>x,err := something() orelse {
>> handleErrorAndReturn
>> } 
>> You do not think this is a significant  reduction in boilerplate? The 
>> only thing that will do a better job is a try-catch which is not acceptable 
>> to the Go team (fortunately). 
>>
>> why the line-by-line would break with orelse? they are working fine with 
>> the one-liner you cited:
>>   if x,err := something() ; err != nil 
>>
>> Why it won't work with one time retires? That is like one time retires 
>> won't work in an if-else block.
>>
>> Thanks again,
>>
>> On Monday, July 31, 2023 at 3:59:50 PM UTC-6 Tim Casey wrote:
>>
>>>
>>>
>>> I do not think this reduces boilerplate code.  This compacts it, which 
>>> is different.
>>>
>>> I think any one-liner-return-on-err makes the language harder to debug.  
>>> It is very common breakpoints are set for exceptional cases, which tend to 
>>> be 

[go-nuts] Re: Error handling

2023-08-01 Thread Stephen Illingworth


On Tuesday, 1 August 2023 at 18:06:25 UTC+1 DrGo wrote:

Compare the following; which one would you prefer to read a lot of?


You've asked a fair question so you deserve an honest answer. Looking at 
the two examples, I would prefer to read the code in the first example.

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/5c32bdce-b07c-4703-b445-4a2a2d95a0f5n%40googlegroups.com.


[go-nuts] Re: Error handling

2023-08-01 Thread DrGo
Thanks. 
The keystroke saving is not the motivation. The aim is to reduce the code 
reader’s mental load. My approach allows for clearer code where the main 
program logic is not dwarfed by the error handling code while maintaining 
the explicitly of error handling and the possible error-induced 
interruption in program flow. It avoids creating new if scope when one is 
not desired and offers opportunities for further deduplication of error 
handling code although each error is still handled individually. Compare 
the following; which one would you prefer to read a lot of?

- current approach; error handling to program logic ratio: 13:5 

func CopyFile(src, dst string) error {
r, err := os.Open(src)
if err != nil {
return fmt.Errorf("copy %s %s: %v", src, dst, err)
}
defer r.Close()

w, err := os.Create(dst)
if err != nil {
return fmt.Errorf("copy %s %s: %v", src, dst, err)
}

if _, err := io.Copy(w, r); err != nil {
w.Close()
os.Remove(dst)
return fmt.Errorf("copy %s %s: %v", src, dst, err)
}

if err := w.Close(); err != nil {
os.Remove(dst)
return fmt.Errorf("copy %s %s: %v", src, dst, err)
}
}

- new approach ratio 5:5
func CopyFile(src, dst string) error {
r, err := os.Open(src) *orelse* return fmt.Errorf("copy %s %s: %v", src, 
dst, err)
defer r.Close()

w, err := os.Create(dst); *orelse* return fmt.Errorf("copy %s %s: %v", src, 
dst, err)
err := io.Copy(w, r) *orelse* {
w.Close()
os.Remove(dst)
return fmt.Errorf("copy %s %s: %v", src, dst, err)
}

err := w.Close() *orelse* {
os.Remove(dst)
return fmt.Errorf("copy %s %s: %v", src, dst, err)
}
}

On Sunday, July 30, 2023 at 9:27:27 PM UTC-6 Marcello H wrote:

> I think the current error handling is just fine.
> For the extra typing, they invented keyboard snippets and such.
>
> But for this proposal, I would like to see how a return with multiple 
> values would look to get a better understanding.
> ```
> // translate this in the proposed solution?
> func myFirstFunction() (string, err) {
>result, err := myFunction()
>if err != nill {
>return rest, err
>}
> }
> ```
>
> Op maandag 31 juli 2023 om 04:32:01 UTC+2 schreef DrGo:
>
>> Another possibility Jeremy is that the orelse block is executed if any of 
>> the returned error values is not nil. 
>>
>> On Sunday, July 30, 2023 at 8:14:58 PM UTC-6 DrGo wrote:
>>
>>> Thanks...
>>> yes indeed. Too many requirements but I think this solution comes close 
>>> to meeting them. If a rare function returns more than one error value (yet 
>>> to see one in the wild) then the compiler should reject orelse use and the 
>>> user can fallback on the (the if err!= nil) approach. 
>>>
>>> On Sunday, July 30, 2023 at 6:02:57 PM UTC-6 Jeremy French wrote:
>>>
 Also, errors are values, which means - although uncommon - a function 
 could return two or more error values.  Which would orelse evaluate?  Even 
 if you arbitrarily chose one, that would violate the explicit vs implicit 
 code flow principle.  

 My sympathies, OP.  I too hate the "if err!= nil" boilerplate, and have 
 suggested my own idea for fixing it, which was similarly dismantled for 
 good reasons by those more knowledgeable than me.  The truth is, this 
 problem/issue has so many restrictions placed on it (currently idiomatic 
 principles, backwards compatibility promise, explicit vs implicit, etc) 
 that the set of possible solutions is VERY narrow, possibly infinitely so.

 On Sunday, July 30, 2023 at 3:51:49 PM UTC-4 Brian Candler wrote:

 err := io.Copy(w, r) *orelse* {
 w.Close()
 os.Remove(dst)
 return fmt.Errorf("copy %s %s: %v", src, dst, err)
 }

 My question still stands. Semantically, what value exactly does the 
 "orelse" condition test is not equal to nil?

 - does it test the value from the preceding assignment? If so, is 
 "orelse" only valid immediately following an assignment expression? The 
 original posting didn't say this.  And if it *is* linked to an assignment 
 expression which assigns multiple values, does it only look at the last 
 value? (Again, that was not specified)

 - does it always test a variable called "err"? The original posting 
 said it was equivalent to "if err!=nil" but a later post contradicted this

 - does it test the value from the 'return' expression at the end of the 
 block following orelse? Except in this case, it can't because it's buried 
 inside fmt.Errorf

 On Sunday, 30 July 2023 at 17:55:34 UTC+1 DrGo wrote:

 Good point Harri,

 This is what the correct version will look like using this proposal 

 func CopyFile(src, dst string) error {
 r, err := os.Open(src) *orelse* return fmt.Errorf("copy %s %s: %v", 
 src, dst, err)
 defer r.Close()

 w, err := os.Create(dst); *orelse* return fmt.Errorf("copy %s %s: %v", 
 src, dst, err)
 err := io.Copy(w, r) *orelse* {
 w.Close()
 

Re: [go-nuts] Re: Error handling

2023-08-01 Thread Victor Giordano
I think that the original Author has made a clear point. It has no sense to 
denied that we often write a lot of times things like...

if (err != nil) {
return err
}

So, I understand that some people doesn't bother about that, and that is 
okey. *But for those that doesn't like to write something twice, I guess 
your proposal is a good idea and highlights a boilerplate aspect across any 
golang project.*

Great Idea Dr Go!



El martes, 1 de agosto de 2023 a las 10:32:58 UTC-3, Jeremy French escribió:

> I don't think this argument holds much weight.  I understand and agree 
> that the majority is not always correct.  But then what was the point of 
> the developer survey, if that data is irrelevant?  Isn't the existence of 
> the developer survey an implicit statement by the Go team that they care 
> about what Go developers think?  There is also a very similar argument here 
> which was central to the generics debate and was one of the major arguments 
> in favor of implementing generics - that it would significantly help some 
> people, and it wouldn't hurt anyone else very much.  So similarly, "I don't 
> mind it the way it is" is not a very good argument.  
>
> I don't speak for the Go team, but my impression is that they do care 
> about this issue, and would like to reduce the boilerplate/verbosity of 
> error handling if they could.  But that they have seen hundreds of 
> different proposals (thousands if you include variations on a theme), and 
> haven't found any that qualify for the requirements that are more important 
> to Go's nature than just verbosity.
>
> On Tuesday, August 1, 2023 at 4:10:57 AM UTC-4 Jan Mercl wrote:
>
>> On Tue, Aug 1, 2023 at 1:47 AM DrGo  wrote: 
>>
>> > The verbosity of error handling is the number one concern for Go 
>> developers in the most recent survey. 
>>
>> That says something about those developers, about their preferences, 
>> opinions, taste etc and that it differs from what the Original 
>> Language Designers (OLD™) preferred. 
>>
>> It has close to zero bits of information which preferences are the 
>> better ones. It's a subjective category anyway. 
>>
>> > So there is a need for doing something about it.. 
>>
>> And here's IMO the mistake. You may feel the need, Joe and Mary may 
>> not. It's ok to have preferences. It's ok for preferences to be 
>> different. It does not mean there's a need to change anything. Of 
>> course, you can decide that following the preferences of a majority of 
>> developers is a rational move. 
>>
>> I claim it a fallacy. A big one. Let me not joke about billion flies, 
>> but the fact is - language designers are few and far between while 
>> developers come in heaps. And let's be honest. Most developers write 
>> horrible code, me included. Maybe you're the rare exception, congrats 
>> then. But the majority of us are just the ordinary, average coders for 
>> hire. There are deadlines to meet, bills to pay, project mis-managers 
>> getting into the way etc. We have all experienced that, didn't we? 
>>
>> I, for one learned to pay much more attention to what language 
>> designers do and say. Sometimes I agree, sometime I don't. But I 
>> believe one can, in essence, ignore what the majority of developers 
>> thinks about it. Actually, I think the majority of developers is wrong 
>> more often than the, most of the time silent, minority. 
>>
>> -j 
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/227a8423-b52a-47d7-acc4-f47280b2898dn%40googlegroups.com.


Re: [go-nuts] Re: Error handling

2023-08-01 Thread Jeremy French
I don't think this argument holds much weight.  I understand and agree that 
the majority is not always correct.  But then what was the point of the 
developer survey, if that data is irrelevant?  Isn't the existence of the 
developer survey an implicit statement by the Go team that they care about 
what Go developers think?  There is also a very similar argument here which 
was central to the generics debate and was one of the major arguments in 
favor of implementing generics - that it would significantly help some 
people, and it wouldn't hurt anyone else very much.  So similarly, "I don't 
mind it the way it is" is not a very good argument.  

I don't speak for the Go team, but my impression is that they do care about 
this issue, and would like to reduce the boilerplate/verbosity of error 
handling if they could.  But that they have seen hundreds of different 
proposals (thousands if you include variations on a theme), and haven't 
found any that qualify for the requirements that are more important to Go's 
nature than just verbosity.

On Tuesday, August 1, 2023 at 4:10:57 AM UTC-4 Jan Mercl wrote:

> On Tue, Aug 1, 2023 at 1:47 AM DrGo  wrote:
>
> > The verbosity of error handling is the number one concern for Go 
> developers in the most recent survey.
>
> That says something about those developers, about their preferences,
> opinions, taste etc and that it differs from what the Original
> Language Designers (OLD™) preferred.
>
> It has close to zero bits of information which preferences are the
> better ones. It's a subjective category anyway.
>
> > So there is a need for doing something about it..
>
> And here's IMO the mistake. You may feel the need, Joe and Mary may
> not. It's ok to have preferences. It's ok for preferences to be
> different. It does not mean there's a need to change anything. Of
> course, you can decide that following the preferences of a majority of
> developers is a rational move.
>
> I claim it a fallacy. A big one. Let me not joke about billion flies,
> but the fact is - language designers are few and far between while
> developers come in heaps. And let's be honest. Most developers write
> horrible code, me included. Maybe you're the rare exception, congrats
> then. But the majority of us are just the ordinary, average coders for
> hire. There are deadlines to meet, bills to pay, project mis-managers
> getting into the way etc. We have all experienced that, didn't we?
>
> I, for one learned to pay much more attention to what language
> designers do and say. Sometimes I agree, sometime I don't. But I
> believe one can, in essence, ignore what the majority of developers
> thinks about it. Actually, I think the majority of developers is wrong
> more often than the, most of the time silent, minority.
>
> -j
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/7efa2d28-44c6-4089-b28a-90fe770a9003n%40googlegroups.com.


Re: [go-nuts] Re: Error handling

2023-08-01 Thread Jan Mercl
On Tue, Aug 1, 2023 at 1:47 AM DrGo  wrote:

> The verbosity of error handling is the number one concern for Go developers 
> in the most recent survey.

That says something about those developers, about their preferences,
opinions, taste etc and that it differs from what the Original
Language Designers (OLD™) preferred.

It has close to zero bits of information which preferences are the
better ones. It's a subjective category anyway.

> So there is a need for doing something about it..

And here's IMO the mistake. You may feel the need, Joe and Mary may
not. It's ok to have preferences. It's ok for preferences to be
different. It does not mean there's a need to change anything. Of
course, you can decide that following the preferences of a majority of
developers is a rational move.

I claim it a fallacy. A big one. Let me not joke about billion flies,
but the fact is - language designers are few and far between while
developers come in heaps. And let's be honest. Most developers write
horrible code, me included. Maybe you're the rare exception, congrats
then. But the majority of us are just the ordinary, average coders for
hire. There are deadlines to meet, bills to pay, project mis-managers
getting into the way etc. We have all experienced that, didn't we?

I, for one learned to pay much more attention to what language
designers do and say. Sometimes I agree, sometime I don't. But I
believe one can, in essence, ignore what the majority of developers
thinks about it. Actually, I think the majority of developers is wrong
more often than the, most of the time silent, minority.

-j

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/CAA40n-UNPFRR55YYJgWs34jh38p1zf61PpZaWFGiH2_khv1kbg%40mail.gmail.com.


Re: [go-nuts] Re: Error handling

2023-07-31 Thread Tim Casey
>> You do not think this is a significant  reduction in boilerplate?

I understand people having a complaint about the verbosity of error
handling.  But, this follows C code error handling.  So to me, it is not
all *that* bad.
I think the measurable reduction in boilerplate code is ' ; err != nil' for
' orelse '.   And I do not believe this is worth a keyword.  Some of the
context is  being used to C.  And another aspect is being used to perl and
its one liners.  With perl, the debugger is not something which is close to
gdb/adb or the like.  So the comparison is not about saving code.

I would suggest, if I had a bold idea (and probably dumb), to have a
functional way to handle this.   Something like:

HandleErrorChain( todoList []func() (TYPE,error), errorHandler func ()
TYPE, error ) (TYPE, error)

Which means, I have a list of things I want to do and I want the error
handling to be all the same for all of them.  Then the *chain* of things
would make sense with a single handler.  This has the expense of being
kinda odd so at the very least it would need idiomatic polishing.  I also
think I am too ignorant to have a real say in any of this.

>> Why it won't work with one time retires? That is like one time retires
won't work in an if-else block

I think there is a bit of talking past each other here.  Or at least I
dont understand.  I think orelse is too specific to be helpful.  That is,
it is too precise to reduce a large swath of what might look like error
handling code, because error handling code can at times be specific.  The
first dumb example I came up with is a simple one-time retry, which I have
put in code at times.  It is usually ugly, but effective:

v,err := dosomething()
if err != nil {
v,err = dosomething()
}
if err != nil {
handleError(err)
   }
   importantOperation(v)

This with the token:

if v,err := dosomething() orelse {
v,err = dosomething() orelse {
handleError()
}
}
importantOperation(v)

The savings is the two 'err != nil' lines.

If I take a step back, some of what I am reacting to is how much it is
discussed.  It *feels*, at least to me as an ignorant person in this
context, as if people were not handling errors previously.  Golang is
forcing this now and the resulting lines of code look like 'too much'
compared to previous lines of code.  But I think this is a direct design
goal.  If the keyword vs lines of code/tokenspace is worth it, so be it.
Who am I to say.  If we are truely circling on a way to handle errors in a
chain, then the chain aspect is at least as important as any one line, and
up to this point has largely been ignored.

In any event, i dont mean to be argumentative or even contrarian.  Sorry if
it comes across that way.

tim


On Mon, Jul 31, 2023 at 4:46 PM DrGo  wrote:

> Thanks for the valuable feedback,
> The verbosity of error handling is the number one concern for Go
> developers in the most recent survey. So there is a need for doing
> something about it.. except that there are many possibly conflicting
> requirements outlined by the Go team.
> The problem with the abbreviated if err!= nil in your example:
>   if x,err := something() ; err != nil {
> handleErrorAndReturn
> }
> is that x is local to the if scope and often that won't work forcing the
> more verbose:
>x,err := something()
>   if err != nil {
> handleErrorAndReturn
> }
> If you have few of those as is the case in io programs; there is real
> impact on the readability of the code.
> the oresle approach avoids that problem (the x stays in the scope of the
> func).
>
>x,err := something() orelse {
> handleErrorAndReturn
> }
> You do not think this is a significant  reduction in boilerplate? The only
> thing that will do a better job is a try-catch which is not acceptable to
> the Go team (fortunately).
>
> why the line-by-line would break with orelse? they are working fine with
> the one-liner you cited:
>   if x,err := something() ; err != nil
>
> Why it won't work with one time retires? That is like one time retires
> won't work in an if-else block.
>
> Thanks again,
>
> On Monday, July 31, 2023 at 3:59:50 PM UTC-6 Tim Casey wrote:
>
>>
>>
>> I do not think this reduces boilerplate code.  This compacts it, which is
>> different.
>>
>> I think any one-liner-return-on-err makes the language harder to debug.
>> It is very common breakpoints are set for exceptional cases, which tend to
>> be surprising.  If the test and the return are on the same line then all of
>> the line-by-line tools will break down, at least a little bit.
>>
>> If you see:
>> x,err := something() ; err != nil {
>> handleErrorAndReturn
>> }
>>
>> At the very least, the template will not work for things like one time
>> retries, if error do something else, log the error and
>> DoSomethingAdditional().  This would be a sub scope and in golang i would
>> expect this to have '{}' as part of 

Re: [go-nuts] Re: Error handling

2023-07-31 Thread DrGo
Thanks for the valuable feedback,
The verbosity of error handling is the number one concern for Go developers 
in the most recent survey. So there is a need for doing something about 
it.. except that there are many possibly conflicting requirements outlined 
by the Go team. 
The problem with the abbreviated if err!= nil in your example:
  if x,err := something() ; err != nil {
handleErrorAndReturn
}
is that x is local to the if scope and often that won't work forcing the 
more verbose:
   x,err := something()
  if err != nil {
handleErrorAndReturn
} 
If you have few of those as is the case in io programs; there is real 
impact on the readability of the code.
the oresle approach avoids that problem (the x stays in the scope of the 
func).

   x,err := something() orelse {
handleErrorAndReturn
} 
You do not think this is a significant  reduction in boilerplate? The only 
thing that will do a better job is a try-catch which is not acceptable to 
the Go team (fortunately). 

why the line-by-line would break with orelse? they are working fine with 
the one-liner you cited:
  if x,err := something() ; err != nil 

Why it won't work with one time retires? That is like one time retires 
won't work in an if-else block.

Thanks again,

On Monday, July 31, 2023 at 3:59:50 PM UTC-6 Tim Casey wrote:

>
>
> I do not think this reduces boilerplate code.  This compacts it, which is 
> different.
>
> I think any one-liner-return-on-err makes the language harder to debug.  
> It is very common breakpoints are set for exceptional cases, which tend to 
> be surprising.  If the test and the return are on the same line then all of 
> the line-by-line tools will break down, at least a little bit.
>
> If you see:
> x,err := something() ; err != nil {
> handleErrorAndReturn
> }
>
> At the very least, the template will not work for things like one time 
> retries, if error do something else, log the error and 
> DoSomethingAdditional().  This would be a sub scope and in golang i would 
> expect this to have '{}' as part of the scope shift.  If this is 
> acceptable, then you are very likely to be on a separate line in any 
> event.  So the original looks like:
>
>   err := io.Copy(w, r) *orelse* {
> DoSomethingElse()
> }
>
> This means the only 'boilerplate' is 'orelse' <- '; err != nil', which 
> seems rather expensive for this error handling.
>
> As a slight change of subject, I find the whole discussion about 'saving' 
> boilerplate to be well over-stated, too much work and energy (at least by 
> me as an outside observer).  Having something which fits within the design 
> of the language, making it a developer centric language, would seem to 
> fight with any one-line-template approach.
>
> tim
>
>
>
>
>
> The test and the handle all fit on one line.   I dont think having a 
> single line return, like perl 'next if STATEMENT' style fits within golang 
> language goals.
>
> On Mon, Jul 31, 2023 at 8:18 AM DrGo  wrote:
>
>> Me too but I do not have high hopes
>>
>>
>> On Monday, July 31, 2023 at 12:10:24 AM UTC-6 Mark wrote:
>>
>>> Given that this proposal is to reduce boilerplate, and assuming the 
>>> semantic issues could be solved, it seems to me that the 'return' is 
>>> redundant (i.e., could be implicit) and that 'orelse' could be done with 
>>> the existing 'else' keyword, i.e.,
>>>
>>> ```
>>> result, err := someCall() else rest, err
>>> ```
>>> Anyway, I really do hope the long-winded error syntax gets solved 
>>> somehow!
>>>
>>> On Monday, July 31, 2023 at 5:41:49 AM UTC+1 DrGo wrote:
>>>
 func myFirstFunction() (string, err) {

result, err := myFunction() orelse return rest, err

 }

 On Sunday, July 30, 2023 at 9:27:27 PM UTC-6 Marcello H wrote:

> I think the current error handling is just fine.
> For the extra typing, they invented keyboard snippets and such.
>
> But for this proposal, I would like to see how a return with multiple 
> values would look to get a better understanding.
> ```
> // translate this in the proposed solution?
> func myFirstFunction() (string, err) {
>result, err := myFunction()
>if err != nill {
>return rest, err
>}
> }
> ```
>
> Op maandag 31 juli 2023 om 04:32:01 UTC+2 schreef DrGo:
>
>> Another possibility Jeremy is that the orelse block is executed if 
>> any of the returned error values is not nil. 
>>
>> On Sunday, July 30, 2023 at 8:14:58 PM UTC-6 DrGo wrote:
>>
>>> Thanks...
>>> yes indeed. Too many requirements but I think this solution comes 
>>> close to meeting them. If a rare function returns more than one error 
>>> value 
>>> (yet to see one in the wild) then the compiler should reject orelse use 
>>> and 
>>> the user can fallback on the (the if err!= nil) approach. 
>>>
>>> On Sunday, July 30, 2023 at 6:02:57 PM UTC-6 Jeremy French wrote:

Re: [go-nuts] Re: Error handling

2023-07-31 Thread Tim Casey
I do not think this reduces boilerplate code.  This compacts it, which is
different.

I think any one-liner-return-on-err makes the language harder to debug.  It
is very common breakpoints are set for exceptional cases, which tend to be
surprising.  If the test and the return are on the same line then all of
the line-by-line tools will break down, at least a little bit.

If you see:
x,err := something() ; err != nil {
handleErrorAndReturn
}

At the very least, the template will not work for things like one time
retries, if error do something else, log the error and
DoSomethingAdditional().  This would be a sub scope and in golang i would
expect this to have '{}' as part of the scope shift.  If this is
acceptable, then you are very likely to be on a separate line in any
event.  So the original looks like:

  err := io.Copy(w, r) *orelse* {
DoSomethingElse()
}

This means the only 'boilerplate' is 'orelse' <- '; err != nil', which
seems rather expensive for this error handling.

As a slight change of subject, I find the whole discussion about 'saving'
boilerplate to be well over-stated, too much work and energy (at least by
me as an outside observer).  Having something which fits within the design
of the language, making it a developer centric language, would seem to
fight with any one-line-template approach.

tim





The test and the handle all fit on one line.   I dont think having a single
line return, like perl 'next if STATEMENT' style fits within golang
language goals.

On Mon, Jul 31, 2023 at 8:18 AM DrGo  wrote:

> Me too but I do not have high hopes
>
>
> On Monday, July 31, 2023 at 12:10:24 AM UTC-6 Mark wrote:
>
>> Given that this proposal is to reduce boilerplate, and assuming the
>> semantic issues could be solved, it seems to me that the 'return' is
>> redundant (i.e., could be implicit) and that 'orelse' could be done with
>> the existing 'else' keyword, i.e.,
>>
>> ```
>> result, err := someCall() else rest, err
>> ```
>> Anyway, I really do hope the long-winded error syntax gets solved somehow!
>>
>> On Monday, July 31, 2023 at 5:41:49 AM UTC+1 DrGo wrote:
>>
>>> func myFirstFunction() (string, err) {
>>>
>>>result, err := myFunction() orelse return rest, err
>>>
>>> }
>>>
>>> On Sunday, July 30, 2023 at 9:27:27 PM UTC-6 Marcello H wrote:
>>>
 I think the current error handling is just fine.
 For the extra typing, they invented keyboard snippets and such.

 But for this proposal, I would like to see how a return with multiple
 values would look to get a better understanding.
 ```
 // translate this in the proposed solution?
 func myFirstFunction() (string, err) {
result, err := myFunction()
if err != nill {
return rest, err
}
 }
 ```

 Op maandag 31 juli 2023 om 04:32:01 UTC+2 schreef DrGo:

> Another possibility Jeremy is that the orelse block is executed if any
> of the returned error values is not nil.
>
> On Sunday, July 30, 2023 at 8:14:58 PM UTC-6 DrGo wrote:
>
>> Thanks...
>> yes indeed. Too many requirements but I think this solution comes
>> close to meeting them. If a rare function returns more than one error 
>> value
>> (yet to see one in the wild) then the compiler should reject orelse use 
>> and
>> the user can fallback on the (the if err!= nil) approach.
>>
>> On Sunday, July 30, 2023 at 6:02:57 PM UTC-6 Jeremy French wrote:
>>
>>> Also, errors are values, which means - although uncommon - a
>>> function could return two or more error values.  Which would orelse
>>> evaluate?  Even if you arbitrarily chose one, that would violate the
>>> explicit vs implicit code flow principle.
>>>
>>> My sympathies, OP.  I too hate the "if err!= nil" boilerplate, and
>>> have suggested my own idea for fixing it, which was similarly dismantled
>>> for good reasons by those more knowledgeable than me.  The truth is, 
>>> this
>>> problem/issue has so many restrictions placed on it (currently idiomatic
>>> principles, backwards compatibility promise, explicit vs implicit, etc)
>>> that the set of possible solutions is VERY narrow, possibly infinitely 
>>> so.
>>>
>>> On Sunday, July 30, 2023 at 3:51:49 PM UTC-4 Brian Candler wrote:
>>>
>>> err := io.Copy(w, r) *orelse* {
>>> w.Close()
>>> os.Remove(dst)
>>> return fmt.Errorf("copy %s %s: %v", src, dst, err)
>>> }
>>>
>>> My question still stands. Semantically, what value exactly does the
>>> "orelse" condition test is not equal to nil?
>>>
>>> - does it test the value from the preceding assignment? If so, is
>>> "orelse" only valid immediately following an assignment expression? The
>>> original posting didn't say this.  And if it *is* linked to an 
>>> assignment
>>> expression which assigns multiple values, does it only look at the last
>>> value? 

[go-nuts] Re: Error handling

2023-07-31 Thread DrGo
Me too but I do not have high hopes


On Monday, July 31, 2023 at 12:10:24 AM UTC-6 Mark wrote:

> Given that this proposal is to reduce boilerplate, and assuming the 
> semantic issues could be solved, it seems to me that the 'return' is 
> redundant (i.e., could be implicit) and that 'orelse' could be done with 
> the existing 'else' keyword, i.e.,
>
> ```
> result, err := someCall() else rest, err
> ```
> Anyway, I really do hope the long-winded error syntax gets solved somehow!
>
> On Monday, July 31, 2023 at 5:41:49 AM UTC+1 DrGo wrote:
>
>> func myFirstFunction() (string, err) {
>>
>>result, err := myFunction() orelse return rest, err
>>
>> }
>>
>> On Sunday, July 30, 2023 at 9:27:27 PM UTC-6 Marcello H wrote:
>>
>>> I think the current error handling is just fine.
>>> For the extra typing, they invented keyboard snippets and such.
>>>
>>> But for this proposal, I would like to see how a return with multiple 
>>> values would look to get a better understanding.
>>> ```
>>> // translate this in the proposed solution?
>>> func myFirstFunction() (string, err) {
>>>result, err := myFunction()
>>>if err != nill {
>>>return rest, err
>>>}
>>> }
>>> ```
>>>
>>> Op maandag 31 juli 2023 om 04:32:01 UTC+2 schreef DrGo:
>>>
 Another possibility Jeremy is that the orelse block is executed if any 
 of the returned error values is not nil. 

 On Sunday, July 30, 2023 at 8:14:58 PM UTC-6 DrGo wrote:

> Thanks...
> yes indeed. Too many requirements but I think this solution comes 
> close to meeting them. If a rare function returns more than one error 
> value 
> (yet to see one in the wild) then the compiler should reject orelse use 
> and 
> the user can fallback on the (the if err!= nil) approach. 
>
> On Sunday, July 30, 2023 at 6:02:57 PM UTC-6 Jeremy French wrote:
>
>> Also, errors are values, which means - although uncommon - a function 
>> could return two or more error values.  Which would orelse evaluate?  
>> Even 
>> if you arbitrarily chose one, that would violate the explicit vs 
>> implicit 
>> code flow principle.  
>>
>> My sympathies, OP.  I too hate the "if err!= nil" boilerplate, and 
>> have suggested my own idea for fixing it, which was similarly dismantled 
>> for good reasons by those more knowledgeable than me.  The truth is, 
>> this 
>> problem/issue has so many restrictions placed on it (currently idiomatic 
>> principles, backwards compatibility promise, explicit vs implicit, etc) 
>> that the set of possible solutions is VERY narrow, possibly infinitely 
>> so.
>>
>> On Sunday, July 30, 2023 at 3:51:49 PM UTC-4 Brian Candler wrote:
>>
>> err := io.Copy(w, r) *orelse* {
>> w.Close()
>> os.Remove(dst)
>> return fmt.Errorf("copy %s %s: %v", src, dst, err)
>> }
>>
>> My question still stands. Semantically, what value exactly does the 
>> "orelse" condition test is not equal to nil?
>>
>> - does it test the value from the preceding assignment? If so, is 
>> "orelse" only valid immediately following an assignment expression? The 
>> original posting didn't say this.  And if it *is* linked to an 
>> assignment 
>> expression which assigns multiple values, does it only look at the last 
>> value? (Again, that was not specified)
>>
>> - does it always test a variable called "err"? The original posting 
>> said it was equivalent to "if err!=nil" but a later post contradicted 
>> this
>>
>> - does it test the value from the 'return' expression at the end of 
>> the block following orelse? Except in this case, it can't because it's 
>> buried inside fmt.Errorf
>>
>> On Sunday, 30 July 2023 at 17:55:34 UTC+1 DrGo wrote:
>>
>> Good point Harri,
>>
>> This is what the correct version will look like using this proposal 
>>
>> func CopyFile(src, dst string) error {
>> r, err := os.Open(src) *orelse* return fmt.Errorf("copy %s %s: %v", 
>> src, dst, err)
>> defer r.Close()
>>
>> w, err := os.Create(dst); *orelse* return fmt.Errorf("copy %s %s: %v", 
>> src, dst, err)
>> err := io.Copy(w, r) *orelse* {
>> w.Close()
>> os.Remove(dst)
>> return fmt.Errorf("copy %s %s: %v", src, dst, err)
>> }
>>
>> err := w.Close() *orelse* {
>> os.Remove(dst)
>> return fmt.Errorf("copy %s %s: %v", src, dst, err)
>> }
>> }
>>
>> In a more complex func, the error formatting/handling code can be 
>> further deduplicated by extracting it into a closure. 
>> e.g., 
>>
>> func CopyFile(src, dst string) error {
>> copyErr:= func(err error) {
>> return fmt.Errorf("copy %s %s: %v", src, dst, err)
>> } 
>> r, err := os.Open(src) *orelse* return copyErr(err) 
>> defer r.Close()
>>
>> w, err := os.Create(dst); *orelse* return copyErr(err)

[go-nuts] Re: Error handling

2023-07-31 Thread 'Mark' via golang-nuts
Given that this proposal is to reduce boilerplate, and assuming the 
semantic issues could be solved, it seems to me that the 'return' is 
redundant (i.e., could be implicit) and that 'orelse' could be done with 
the existing 'else' keyword, i.e.,

```
result, err := someCall() else rest, err
```
Anyway, I really do hope the long-winded error syntax gets solved somehow!

On Monday, July 31, 2023 at 5:41:49 AM UTC+1 DrGo wrote:

> func myFirstFunction() (string, err) {
>
>result, err := myFunction() orelse return rest, err
>
> }
>
> On Sunday, July 30, 2023 at 9:27:27 PM UTC-6 Marcello H wrote:
>
>> I think the current error handling is just fine.
>> For the extra typing, they invented keyboard snippets and such.
>>
>> But for this proposal, I would like to see how a return with multiple 
>> values would look to get a better understanding.
>> ```
>> // translate this in the proposed solution?
>> func myFirstFunction() (string, err) {
>>result, err := myFunction()
>>if err != nill {
>>return rest, err
>>}
>> }
>> ```
>>
>> Op maandag 31 juli 2023 om 04:32:01 UTC+2 schreef DrGo:
>>
>>> Another possibility Jeremy is that the orelse block is executed if any 
>>> of the returned error values is not nil. 
>>>
>>> On Sunday, July 30, 2023 at 8:14:58 PM UTC-6 DrGo wrote:
>>>
 Thanks...
 yes indeed. Too many requirements but I think this solution comes close 
 to meeting them. If a rare function returns more than one error value (yet 
 to see one in the wild) then the compiler should reject orelse use and the 
 user can fallback on the (the if err!= nil) approach. 

 On Sunday, July 30, 2023 at 6:02:57 PM UTC-6 Jeremy French wrote:

> Also, errors are values, which means - although uncommon - a function 
> could return two or more error values.  Which would orelse evaluate?  
> Even 
> if you arbitrarily chose one, that would violate the explicit vs implicit 
> code flow principle.  
>
> My sympathies, OP.  I too hate the "if err!= nil" boilerplate, and 
> have suggested my own idea for fixing it, which was similarly dismantled 
> for good reasons by those more knowledgeable than me.  The truth is, this 
> problem/issue has so many restrictions placed on it (currently idiomatic 
> principles, backwards compatibility promise, explicit vs implicit, etc) 
> that the set of possible solutions is VERY narrow, possibly infinitely so.
>
> On Sunday, July 30, 2023 at 3:51:49 PM UTC-4 Brian Candler wrote:
>
> err := io.Copy(w, r) *orelse* {
> w.Close()
> os.Remove(dst)
> return fmt.Errorf("copy %s %s: %v", src, dst, err)
> }
>
> My question still stands. Semantically, what value exactly does the 
> "orelse" condition test is not equal to nil?
>
> - does it test the value from the preceding assignment? If so, is 
> "orelse" only valid immediately following an assignment expression? The 
> original posting didn't say this.  And if it *is* linked to an assignment 
> expression which assigns multiple values, does it only look at the last 
> value? (Again, that was not specified)
>
> - does it always test a variable called "err"? The original posting 
> said it was equivalent to "if err!=nil" but a later post contradicted this
>
> - does it test the value from the 'return' expression at the end of 
> the block following orelse? Except in this case, it can't because it's 
> buried inside fmt.Errorf
>
> On Sunday, 30 July 2023 at 17:55:34 UTC+1 DrGo wrote:
>
> Good point Harri,
>
> This is what the correct version will look like using this proposal 
>
> func CopyFile(src, dst string) error {
> r, err := os.Open(src) *orelse* return fmt.Errorf("copy %s %s: %v", 
> src, dst, err)
> defer r.Close()
>
> w, err := os.Create(dst); *orelse* return fmt.Errorf("copy %s %s: %v", 
> src, dst, err)
> err := io.Copy(w, r) *orelse* {
> w.Close()
> os.Remove(dst)
> return fmt.Errorf("copy %s %s: %v", src, dst, err)
> }
>
> err := w.Close() *orelse* {
> os.Remove(dst)
> return fmt.Errorf("copy %s %s: %v", src, dst, err)
> }
> }
>
> In a more complex func, the error formatting/handling code can be 
> further deduplicated by extracting it into a closure. 
> e.g., 
>
> func CopyFile(src, dst string) error {
> copyErr:= func(err error) {
> return fmt.Errorf("copy %s %s: %v", src, dst, err)
> } 
> r, err := os.Open(src) *orelse* return copyErr(err) 
> defer r.Close()
>
> w, err := os.Create(dst); *orelse* return copyErr(err)
> err := io.Copy(w, r) *orelse* {
> w.Close()
> os.Remove(dst)
> return copyErr(err)
> }
>
> err := w.Close() *orelse* {
> os.Remove(dst)
> return copyErr(err)
> }
> }
>
> On Sunday, July 30, 2023 at 8:17:31 AM UTC-6 Harri L wrote:

[go-nuts] Re: Error handling

2023-07-30 Thread Marcello H
I think the current error handling is just fine.
For the extra typing, they invented keyboard snippets and such.

But for this proposal, I would like to see how a return with multiple 
values would look to get a better understanding.
```
// translate this in the proposed solution?
func myFirstFunction() (string, err) {
   result, err := myFunction()
   if err != nill {
   return rest, err
   }
}
```

Op maandag 31 juli 2023 om 04:32:01 UTC+2 schreef DrGo:

> Another possibility Jeremy is that the orelse block is executed if any of 
> the returned error values is not nil. 
>
> On Sunday, July 30, 2023 at 8:14:58 PM UTC-6 DrGo wrote:
>
>> Thanks...
>> yes indeed. Too many requirements but I think this solution comes close 
>> to meeting them. If a rare function returns more than one error value (yet 
>> to see one in the wild) then the compiler should reject orelse use and the 
>> user can fallback on the (the if err!= nil) approach. 
>>
>> On Sunday, July 30, 2023 at 6:02:57 PM UTC-6 Jeremy French wrote:
>>
>>> Also, errors are values, which means - although uncommon - a function 
>>> could return two or more error values.  Which would orelse evaluate?  Even 
>>> if you arbitrarily chose one, that would violate the explicit vs implicit 
>>> code flow principle.  
>>>
>>> My sympathies, OP.  I too hate the "if err!= nil" boilerplate, and have 
>>> suggested my own idea for fixing it, which was similarly dismantled for 
>>> good reasons by those more knowledgeable than me.  The truth is, this 
>>> problem/issue has so many restrictions placed on it (currently idiomatic 
>>> principles, backwards compatibility promise, explicit vs implicit, etc) 
>>> that the set of possible solutions is VERY narrow, possibly infinitely so.
>>>
>>> On Sunday, July 30, 2023 at 3:51:49 PM UTC-4 Brian Candler wrote:
>>>
>>> err := io.Copy(w, r) *orelse* {
>>> w.Close()
>>> os.Remove(dst)
>>> return fmt.Errorf("copy %s %s: %v", src, dst, err)
>>> }
>>>
>>> My question still stands. Semantically, what value exactly does the 
>>> "orelse" condition test is not equal to nil?
>>>
>>> - does it test the value from the preceding assignment? If so, is 
>>> "orelse" only valid immediately following an assignment expression? The 
>>> original posting didn't say this.  And if it *is* linked to an assignment 
>>> expression which assigns multiple values, does it only look at the last 
>>> value? (Again, that was not specified)
>>>
>>> - does it always test a variable called "err"? The original posting said 
>>> it was equivalent to "if err!=nil" but a later post contradicted this
>>>
>>> - does it test the value from the 'return' expression at the end of the 
>>> block following orelse? Except in this case, it can't because it's buried 
>>> inside fmt.Errorf
>>>
>>> On Sunday, 30 July 2023 at 17:55:34 UTC+1 DrGo wrote:
>>>
>>> Good point Harri,
>>>
>>> This is what the correct version will look like using this proposal 
>>>
>>> func CopyFile(src, dst string) error {
>>> r, err := os.Open(src) *orelse* return fmt.Errorf("copy %s %s: %v", 
>>> src, dst, err)
>>> defer r.Close()
>>>
>>> w, err := os.Create(dst); *orelse* return fmt.Errorf("copy %s %s: %v", 
>>> src, dst, err)
>>> err := io.Copy(w, r) *orelse* {
>>> w.Close()
>>> os.Remove(dst)
>>> return fmt.Errorf("copy %s %s: %v", src, dst, err)
>>> }
>>>
>>> err := w.Close() *orelse* {
>>> os.Remove(dst)
>>> return fmt.Errorf("copy %s %s: %v", src, dst, err)
>>> }
>>> }
>>>
>>> In a more complex func, the error formatting/handling code can be 
>>> further deduplicated by extracting it into a closure. 
>>> e.g., 
>>>
>>> func CopyFile(src, dst string) error {
>>> copyErr:= func(err error) {
>>> return fmt.Errorf("copy %s %s: %v", src, dst, err)
>>> } 
>>> r, err := os.Open(src) *orelse* return copyErr(err) 
>>> defer r.Close()
>>>
>>> w, err := os.Create(dst); *orelse* return copyErr(err)
>>> err := io.Copy(w, r) *orelse* {
>>> w.Close()
>>> os.Remove(dst)
>>> return copyErr(err)
>>> }
>>>
>>> err := w.Close() *orelse* {
>>> os.Remove(dst)
>>> return copyErr(err)
>>> }
>>> }
>>>
>>> On Sunday, July 30, 2023 at 8:17:31 AM UTC-6 Harri L wrote:
>>>
>>> IMHO, you have used the irrelevant example (== 2nd code block) from Russ 
>>> Cox's paper. The paper says:
>>> > This code is not nice, not clean, not elegant, *and still wrong:* 
>>> like the previous version, it does not remove dst when io.Copy or 
>>> w.Close fails.
>>>
>>> I want to compare your proposal with the third example from the paper, 
>>> which does (proper) error annotation and cleanup. Thanks.
>>> On Sunday, July 30, 2023 at 8:57:15 AM UTC+3 DrGo wrote:
>>>
>>> I looked at the long list of proposals to improve error handling in go 
>>> but I have not seen the one I am describing below. If I missed a similar , 
>>> can you pls direct me to where I can find it. If not what do you think of 
>>> this approach. 
>>>
>>> This involves introducing a new keyword "orelse" that is a syntactic 
>>> sugar for an "if err!=nil" block.
>>>

[go-nuts] Re: Error handling

2023-07-30 Thread Jeremy French
Also, errors are values, which means - although uncommon - a function could 
return two or more error values.  Which would orelse evaluate?  Even if you 
arbitrarily chose one, that would violate the explicit vs implicit code 
flow principle.  

My sympathies, OP.  I too hate the "if err!= nil" boilerplate, and have 
suggested my own idea for fixing it, which was similarly dismantled for 
good reasons by those more knowledgeable than me.  The truth is, this 
problem/issue has so many restrictions placed on it (currently idiomatic 
principles, backwards compatibility promise, explicit vs implicit, etc) 
that the set of possible solutions is VERY narrow, possibly infinitely so.

On Sunday, July 30, 2023 at 3:51:49 PM UTC-4 Brian Candler wrote:

err := io.Copy(w, r) *orelse* {
w.Close()
os.Remove(dst)
return fmt.Errorf("copy %s %s: %v", src, dst, err)
}

My question still stands. Semantically, what value exactly does the 
"orelse" condition test is not equal to nil?

- does it test the value from the preceding assignment? If so, is "orelse" 
only valid immediately following an assignment expression? The original 
posting didn't say this.  And if it *is* linked to an assignment expression 
which assigns multiple values, does it only look at the last value? (Again, 
that was not specified)

- does it always test a variable called "err"? The original posting said it 
was equivalent to "if err!=nil" but a later post contradicted this

- does it test the value from the 'return' expression at the end of the 
block following orelse? Except in this case, it can't because it's buried 
inside fmt.Errorf

On Sunday, 30 July 2023 at 17:55:34 UTC+1 DrGo wrote:

Good point Harri,

This is what the correct version will look like using this proposal 

func CopyFile(src, dst string) error {
r, err := os.Open(src) *orelse* return fmt.Errorf("copy %s %s: %v", src, 
dst, err)
defer r.Close()

w, err := os.Create(dst); *orelse* return fmt.Errorf("copy %s %s: %v", src, 
dst, err)
err := io.Copy(w, r) *orelse* {
w.Close()
os.Remove(dst)
return fmt.Errorf("copy %s %s: %v", src, dst, err)
}

err := w.Close() *orelse* {
os.Remove(dst)
return fmt.Errorf("copy %s %s: %v", src, dst, err)
}
}

In a more complex func, the error formatting/handling code can be further 
deduplicated by extracting it into a closure. 
e.g., 

func CopyFile(src, dst string) error {
copyErr:= func(err error) {
return fmt.Errorf("copy %s %s: %v", src, dst, err)
} 
r, err := os.Open(src) *orelse* return copyErr(err) 
defer r.Close()

w, err := os.Create(dst); *orelse* return copyErr(err)
err := io.Copy(w, r) *orelse* {
w.Close()
os.Remove(dst)
return copyErr(err)
}

err := w.Close() *orelse* {
os.Remove(dst)
return copyErr(err)
}
}

On Sunday, July 30, 2023 at 8:17:31 AM UTC-6 Harri L wrote:

IMHO, you have used the irrelevant example (== 2nd code block) from Russ 
Cox's paper. The paper says:
> This code is not nice, not clean, not elegant, *and still wrong:* like 
the previous version, it does not remove dst when io.Copy or w.Close fails.

I want to compare your proposal with the third example from the paper, 
which does (proper) error annotation and cleanup. Thanks.
On Sunday, July 30, 2023 at 8:57:15 AM UTC+3 DrGo wrote:

I looked at the long list of proposals to improve error handling in go but 
I have not seen the one I am describing below. If I missed a similar , can 
you pls direct me to where I can find it. If not what do you think of this 
approach. 

This involves introducing a new keyword "orelse" that is a syntactic sugar 
for an "if err!=nil" block.

The example code in Russ Cox's paper[1] will look something like this:

func CopyFile(src, dst string) error {

r, err := os.Open(src) orelse return err 

defer r.Close()

w, err := os.Create(dst) orelse return err

defer w.Close()

  err = io.Copy(w, r) orelse return err

err = w.Close() orelse return err

}

It is an error to not return an error from an orelse block.

In my eyes, this has the same explicitness and flexibility of the current 
style but is significantly less verbose. It permits ignoring the error, 
returning it as is or wrapping it. Because orelse is not used for any other 
purpose, it would be easy for reviewers and linters to spot lack of error 
handling.  

It also works well with named returns. e.g., 

func returnsObjorErro() (obj Obj, err error) {

  obj, err := createObj() orelse return  //returns nil and err

} 

otherwise orelse is like "else" so e.g., it can be followed by a block if 
additional cleanup or error formatting etc is needed before returning, eg 
w, err := os.Create(dst) orelse {
  
  return err 
}

Similarity to "else" hopefully means that it is easy to learn. It is 
obviously backward compatible  

What do you think?

[1] 
https://go.googlesource.com/proposal/+/master/design/go2draft-error-handling-overview.md

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving 

[go-nuts] Re: Error handling

2023-07-30 Thread Brian Candler
 err := io.Copy(w, r) *orelse* {
w.Close()
os.Remove(dst)
return fmt.Errorf("copy %s %s: %v", src, dst, err)
}

My question still stands. Semantically, what value exactly does the 
"orelse" condition test is not equal to nil?

- does it test the value from the preceding assignment? If so, is "orelse" 
only valid immediately following an assignment expression? The original 
posting didn't say this.  And if it *is* linked to an assignment expression 
which assigns multiple values, does it only look at the last value? (Again, 
that was not specified)

- does it always test a variable called "err"? The original posting said it 
was equivalent to "if err!=nil" but a later post contradicted this

- does it test the value from the 'return' expression at the end of the 
block following orelse? Except in this case, it can't because it's buried 
inside fmt.Errorf

On Sunday, 30 July 2023 at 17:55:34 UTC+1 DrGo wrote:

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

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/7f52cab8-7829-4e8e-9bf4-b1878c3bc7aen%40googlegroups.com.


[go-nuts] Re: Error handling

2023-07-30 Thread DrGo
Good point Harri,

This is what the correct version will look like using this proposal 

func CopyFile(src, dst string) error {
r, err := os.Open(src) *orelse* return fmt.Errorf("copy %s %s: %v", src, 
dst, err)
defer r.Close()

w, err := os.Create(dst); *orelse* return fmt.Errorf("copy %s %s: %v", src, 
dst, err)
err := io.Copy(w, r) *orelse* {
w.Close()
os.Remove(dst)
return fmt.Errorf("copy %s %s: %v", src, dst, err)
}

err := w.Close() *orelse* {
os.Remove(dst)
return fmt.Errorf("copy %s %s: %v", src, dst, err)
}
}

In a more complex func, the error formatting/handling code can be further 
deduplicated by extracting it into a closure. 
e.g., 

func CopyFile(src, dst string) error {
copyErr:= func(err error) {
return fmt.Errorf("copy %s %s: %v", src, dst, err)
} 
r, err := os.Open(src) *orelse* return copyErr(err) 
defer r.Close()

w, err := os.Create(dst); *orelse* return copyErr(err)
err := io.Copy(w, r) *orelse* {
w.Close()
os.Remove(dst)
return copyErr(err)
}

err := w.Close() *orelse* {
os.Remove(dst)
return copyErr(err)
}
}

On Sunday, July 30, 2023 at 8:17:31 AM UTC-6 Harri L wrote:

> IMHO, you have used the irrelevant example (== 2nd code block) from Russ 
> Cox's paper. The paper says:
> > This code is not nice, not clean, not elegant, *and still wrong:* like 
> the previous version, it does not remove dst when io.Copy or w.Close
>  fails.
>
> I want to compare your proposal with the third example from the paper, 
> which does (proper) error annotation and cleanup. Thanks.
> On Sunday, July 30, 2023 at 8:57:15 AM UTC+3 DrGo wrote:
>
>> I looked at the long list of proposals to improve error handling in go 
>> but I have not seen the one I am describing below. If I missed a similar , 
>> can you pls direct me to where I can find it. If not what do you think of 
>> this approach. 
>>
>> This involves introducing a new keyword "orelse" that is a syntactic 
>> sugar for an "if err!=nil" block.
>>
>> The example code in Russ Cox's paper[1] will look something like this:
>>
>> func CopyFile(src, dst string) error {
>>
>> r, err := os.Open(src) orelse return err 
>>
>> defer r.Close()
>>
>> w, err := os.Create(dst) orelse return err
>>
>> defer w.Close()
>>
>>   err = io.Copy(w, r) orelse return err
>>
>> err = w.Close() orelse return err
>>
>> }
>>
>> It is an error to not return an error from an orelse block.
>>
>> In my eyes, this has the same explicitness and flexibility of the current 
>> style but is significantly less verbose. It permits ignoring the error, 
>> returning it as is or wrapping it. Because orelse is not used for any other 
>> purpose, it would be easy for reviewers and linters to spot lack of error 
>> handling.  
>>
>> It also works well with named returns. e.g., 
>>
>> func returnsObjorErro() (obj Obj, err error) {
>>
>>   obj, err := createObj() orelse return  //returns nil and err
>>
>> } 
>>
>> otherwise orelse is like "else" so e.g., it can be followed by a block if 
>> additional cleanup or error formatting etc is needed before returning, eg 
>> w, err := os.Create(dst) orelse {
>>   
>>   return err 
>> }
>>
>> Similarity to "else" hopefully means that it is easy to learn. It is 
>> obviously backward compatible  
>>
>> What do you think?
>>
>> [1] 
>> https://go.googlesource.com/proposal/+/master/design/go2draft-error-handling-overview.md
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/db03dc82-6a11-4593-9f20-d8c5863c1e4an%40googlegroups.com.


[go-nuts] Re: Error handling

2023-07-30 Thread DrGo
Apologies if I am not understanding your question, but does not the 
compiler know the types of all variables (including the returned 
variables)? The compiler will emit code to execute the orelse block if the 
error variable (regardless of its name or concrete type) in the preceding 
statement is not nil; not very different from how it now handles an 
explicit if err!=nil. 

On Sunday, July 30, 2023 at 3:43:29 AM UTC-6 Brian Candler wrote:

> Typo: should have said
>
> var foo error
> r, bar := os.Open(src) orelse return foo   // does this do "if foo != nil 
> { return foo }" ??
>
> On Sunday, 30 July 2023 at 10:20:12 UTC+1 Brian Candler wrote:
>
>> On Sunday, 30 July 2023 at 09:40:25 UTC+1 DrGo wrote:
>>
>> orelse must return an error (ie satisfies the error interface); the 
>> specific type and variable name do not matter.
>>
>>
>> But how does "orelse" perform the check in the first place? Does it look 
>> for the variable named in the return statement?
>>
>> var foo error
>> r, bar := os.Open(src) orelse return foo   // does this do "if foo != nil 
>> { return bar }" ??
>>
>> Also, you are explicitly allowing bare return.  In that case, does it 
>> look at the return values in the function definition?  If the function 
>> returns multiple values, how does it know which one?
>>
>>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/72ca665b-0be9-41df-a25b-bb48ca8c08c4n%40googlegroups.com.


[go-nuts] Re: Error handling

2023-07-30 Thread Harri L
IMHO, you have used the irrelevant example (== 2nd code block) from Russ 
Cox's paper. The paper says:
> This code is not nice, not clean, not elegant, *and still wrong:* like 
the previous version, it does not remove dst when io.Copy or w.Close fails.

I want to compare your proposal with the third example from the paper, 
which does (proper) error annotation and cleanup. Thanks.
On Sunday, July 30, 2023 at 8:57:15 AM UTC+3 DrGo wrote:

> I looked at the long list of proposals to improve error handling in go but 
> I have not seen the one I am describing below. If I missed a similar , can 
> you pls direct me to where I can find it. If not what do you think of this 
> approach. 
>
> This involves introducing a new keyword "orelse" that is a syntactic sugar 
> for an "if err!=nil" block.
>
> The example code in Russ Cox's paper[1] will look something like this:
>
> func CopyFile(src, dst string) error {
>
> r, err := os.Open(src) orelse return err 
>
> defer r.Close()
>
> w, err := os.Create(dst) orelse return err
>
> defer w.Close()
>
>   err = io.Copy(w, r) orelse return err
>
> err = w.Close() orelse return err
>
> }
>
> It is an error to not return an error from an orelse block.
>
> In my eyes, this has the same explicitness and flexibility of the current 
> style but is significantly less verbose. It permits ignoring the error, 
> returning it as is or wrapping it. Because orelse is not used for any other 
> purpose, it would be easy for reviewers and linters to spot lack of error 
> handling.  
>
> It also works well with named returns. e.g., 
>
> func returnsObjorErro() (obj Obj, err error) {
>
>   obj, err := createObj() orelse return  //returns nil and err
>
> } 
>
> otherwise orelse is like "else" so e.g., it can be followed by a block if 
> additional cleanup or error formatting etc is needed before returning, eg 
> w, err := os.Create(dst) orelse {
>   
>   return err 
> }
>
> Similarity to "else" hopefully means that it is easy to learn. It is 
> obviously backward compatible  
>
> What do you think?
>
> [1] 
> https://go.googlesource.com/proposal/+/master/design/go2draft-error-handling-overview.md
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/2f8d00bb-bb77-4932-9ccb-370db58fa9afn%40googlegroups.com.


[go-nuts] Re: Error handling

2023-07-30 Thread Brian Candler
Typo: should have said

var foo error
r, bar := os.Open(src) orelse return foo   // does this do "if foo != nil { 
return foo }" ??

On Sunday, 30 July 2023 at 10:20:12 UTC+1 Brian Candler wrote:

> On Sunday, 30 July 2023 at 09:40:25 UTC+1 DrGo wrote:
>
> orelse must return an error (ie satisfies the error interface); the 
> specific type and variable name do not matter.
>
>
> But how does "orelse" perform the check in the first place? Does it look 
> for the variable named in the return statement?
>
> var foo error
> r, bar := os.Open(src) orelse return foo   // does this do "if foo != nil 
> { return bar }" ??
>
> Also, you are explicitly allowing bare return.  In that case, does it look 
> at the return values in the function definition?  If the function returns 
> multiple values, how does it know which one?
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/0410013a-6036-4f06-9a8b-8900b8dd4765n%40googlegroups.com.


[go-nuts] Re: Error handling

2023-07-30 Thread Brian Candler
On Sunday, 30 July 2023 at 09:40:25 UTC+1 DrGo wrote:

orelse must return an error (ie satisfies the error interface); the 
specific type and variable name do not matter.


But how does "orelse" perform the check in the first place? Does it look 
for the variable named in the return statement?

var foo error
r, bar := os.Open(src) orelse return foo   // does this do "if foo != nil { 
return bar }" ??

Also, you are explicitly allowing bare return.  In that case, does it look 
at the return values in the function definition?  If the function returns 
multiple values, how does it know which one?

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/538f952f-0ad1-4d5f-ac6e-ceb2ab59e6aen%40googlegroups.com.


[go-nuts] Re: Error handling

2023-07-30 Thread DrGo
thanks  for the link.
unlike the onErr approach, my proposal does not treat create special-status 
identifier; the orelse block is like any other else block

On Sunday, July 30, 2023 at 1:31:09 AM UTC-6 Brian Candler wrote:

On Sunday, 30 July 2023 at 06:57:15 UTC+1 DrGo wrote:

I looked at the long list of proposals to improve error handling in go but 
I have not seen the one I am describing below.


There is a meta-ticket here: https://github.com/golang/go/issues/40432

Under the section "Simplifications of if err != nil, to reduce boilerplate" 
I found a link to
https://github.com/golang/go/issues/32946
which seems very similar to yours, using keyword "onErr" after a semicolon, 
instead of "orelse".

if c, err := fn(); onErr { return 0, err }

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/42e423ec-914b-46a0-976d-5ea93d0231f1n%40googlegroups.com.


[go-nuts] Re: Error handling

2023-07-30 Thread DrGo
orelse must return an error (ie satisfies the error interface); the 
specific type and variable name do not matter.
although on second thought.. I am not sure that even that restriction is 
necessary. 

On Sunday, July 30, 2023 at 1:02:04 AM UTC-6 Brian Candler wrote:

Just to be clear: are you hard-coding the variable name "err" into the 
semantics of "orelse"?  That is, you can't assign the error return to a 
variable of any other name?

I disagree that this makes the job of linters any easier than it is today.  
For example, if you'd written

...

   err = io.Copy(w, r)

err = w.Close() orelse return err
}

then you'd still need to detect "value assigned but not used" in the linter 
(assuming it doesn't become *compulsory* to use "orelse" on any assignment 
to a variable called "err")

On Sunday, 30 July 2023 at 06:57:15 UTC+1 DrGo wrote:

I looked at the long list of proposals to improve error handling in go but 
I have not seen the one I am describing below. If I missed a similar , can 
you pls direct me to where I can find it. If not what do you think of this 
approach. 

This involves introducing a new keyword "orelse" that is a syntactic sugar 
for an "if err!=nil" block.

The example code in Russ Cox's paper[1] will look something like this:

func CopyFile(src, dst string) error {

r, err := os.Open(src) orelse return err 

defer r.Close()

w, err := os.Create(dst) orelse return err

defer w.Close()

  err = io.Copy(w, r) orelse return err

err = w.Close() orelse return err

}

It is an error to not return an error from an orelse block.

In my eyes, this has the same explicitness and flexibility of the current 
style but is significantly less verbose. It permits ignoring the error, 
returning it as is or wrapping it. Because orelse is not used for any other 
purpose, it would be easy for reviewers and linters to spot lack of error 
handling.  

It also works well with named returns. e.g., 

func returnsObjorErro() (obj Obj, err error) {

  obj, err := createObj() orelse return  //returns nil and err

} 

otherwise orelse is like "else" so e.g., it can be followed by a block if 
additional cleanup or error formatting etc is needed before returning, eg 
w, err := os.Create(dst) orelse {
  
  return err 
}

Similarity to "else" hopefully means that it is easy to learn. It is 
obviously backward compatible  

What do you think?

[1] 
https://go.googlesource.com/proposal/+/master/design/go2draft-error-handling-overview.md

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/76530e2e-4d48-4ecc-a232-03626ba85e4an%40googlegroups.com.


[go-nuts] Re: Error handling

2023-07-30 Thread Brian Candler


On Sunday, 30 July 2023 at 06:57:15 UTC+1 DrGo wrote:

I looked at the long list of proposals to improve error handling in go but 
I have not seen the one I am describing below.


There is a meta-ticket here: https://github.com/golang/go/issues/40432

Under the section "Simplifications of if err != nil, to reduce boilerplate" 
I found a link to
https://github.com/golang/go/issues/32946
which seems very similar to yours, using keyword "onErr" after a semicolon, 
instead of "orelse".

if c, err := fn(); onErr { return 0, err }

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/0ee7e166-9aac-402c-871c-5e143a606fdbn%40googlegroups.com.


[go-nuts] Re: Error handling

2023-07-30 Thread Brian Candler
Just to be clear: are you hard-coding the variable name "err" into the 
semantics of "orelse"?  That is, you can't assign the error return to a 
variable of any other name?

I disagree that this makes the job of linters any easier than it is today.  
For example, if you'd written

...

   err = io.Copy(w, r)

err = w.Close() orelse return err
}

then you'd still need to detect "value assigned but not used" in the linter 
(assuming it doesn't become *compulsory* to use "orelse" on any assignment 
to a variable called "err")

On Sunday, 30 July 2023 at 06:57:15 UTC+1 DrGo wrote:

> I looked at the long list of proposals to improve error handling in go but 
> I have not seen the one I am describing below. If I missed a similar , can 
> you pls direct me to where I can find it. If not what do you think of this 
> approach. 
>
> This involves introducing a new keyword "orelse" that is a syntactic sugar 
> for an "if err!=nil" block.
>
> The example code in Russ Cox's paper[1] will look something like this:
>
> func CopyFile(src, dst string) error {
>
> r, err := os.Open(src) orelse return err 
>
> defer r.Close()
>
> w, err := os.Create(dst) orelse return err
>
> defer w.Close()
>
>   err = io.Copy(w, r) orelse return err
>
> err = w.Close() orelse return err
>
> }
>
> It is an error to not return an error from an orelse block.
>
> In my eyes, this has the same explicitness and flexibility of the current 
> style but is significantly less verbose. It permits ignoring the error, 
> returning it as is or wrapping it. Because orelse is not used for any other 
> purpose, it would be easy for reviewers and linters to spot lack of error 
> handling.  
>
> It also works well with named returns. e.g., 
>
> func returnsObjorErro() (obj Obj, err error) {
>
>   obj, err := createObj() orelse return  //returns nil and err
>
> } 
>
> otherwise orelse is like "else" so e.g., it can be followed by a block if 
> additional cleanup or error formatting etc is needed before returning, eg 
> w, err := os.Create(dst) orelse {
>   
>   return err 
> }
>
> Similarity to "else" hopefully means that it is easy to learn. It is 
> obviously backward compatible  
>
> What do you think?
>
> [1] 
> https://go.googlesource.com/proposal/+/master/design/go2draft-error-handling-overview.md
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/330e88d9-8072-4614-ae56-8ce9c59517f3n%40googlegroups.com.


[go-nuts] Re: error handling thoughts

2023-07-27 Thread Steve Roth
The warning that I described is one presented by Visual Studio Code with
the vscode-go extension.  Color me stupid for having simply assumed it came
from the compiler.  Based on responses to this thread, I looked more
closely, and found that Mr. Wagner is correct:  it's coming from golint.

I see that golint is deprecated and frozen.  I'm not sure why my vscode-go
is using it, in that case.  Perhaps it's a vestige in my vscode-go
configuration from long ago when it wasn't deprecated.  I hope it's not
used by fresh installs.  At any rate, disabling it seems straightforward.

Thanks, all, for the responses.
Steve


On Thu, Jul 27, 2023 at 8:03 AM Steve Roth  wrote:

> The ongoing Go survey asked a question about satisfaction with error
> handling in Go.  I'd like to express an opinion on it that I haven't seen
> elsewhere, for which there was not room in the survey.
>
> I am generally a fan of the explicit error handling code in Go, but I get
> frustrated by the interactions between error handling, := assignments, and
> compiler warnings.  My preferred way of writing the standard clause is
>
> if err := fn(); err != nil {
>
> // handle error and bail out
> }
>
>
> However, often the function in question returns a result I want to work
> with.  If it's something important for the whole rest of the function, I'll
> probably just define it as a variable at function scope:
>
> var (
>
> result sometype
>
> err error
> )
> // ...
>
> if result, err = fn(); err != nil {
>
> // handle error and bail out
> }
>
> // act on result
>
>
> But often, the result is something I'm only going to use for one statement
> and is not a variable of significance to the whole function.  Those are the
> sorts of cases that := is best for, in my opinion.  In those cases, what
> I'd like to write is
>
> if result, err := fn(); err != nil {
>
> // handle error and bail out
>
> } else {
>
> // act on result
> }
>
>
> Unfortunately, the compiler gives a warning on that.  Because the truth
> clause bailed out (e.g., "return"), it insists that I remove the else and
> turn the code into
>
> if result, err := fn(); err != nil {
>
> // handle error and bail out
>
> }
>
> // act on result
>
>
> But that doesn't compile because result is no longer in scope.
>
> What I often wind up doing instead is
>
> if result, err = fn(); err == nil {
>
> // act on result
>
> } else {
>
> // handle error and bail out
> }
>
>
> That works, but it leaves my code with a mixture of "handle error case
> first, then success" and "handle success case first, then error" patterns,
> which I find adds a lot to cognitive load.
>
> I have no idea whether others share my frustration on this admittedly
> minor point.  But since the survey prodded me, I thought I would voice it
> and see what reactions it gets.  For me, the ideal solution would be to
> suppress the compiler warning about removing the else, when doing so would
> break the code altogether.
>
> Regards,
> Steve
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/CAAnpqKELzWZNSsGsKVW%3DU8hRatw-pJJeBAx_L8WDEnqaALZrqA%40mail.gmail.com.


Re: [go-nuts] Re: error handling thoughts

2023-07-27 Thread 'Axel Wagner' via golang-nuts
It's not a compiler error, but OP is probably referring to golint.
FWIW I also prefer the `if v, err := fn(); err != nil { … }` form, in
general, but in cases like these I just write

v, err := fn()
if err != nil {
// handle error and return
}
// do thing with v

I honestly don't see a huge problem with that.

On Thu, Jul 27, 2023 at 5:34 PM Stephen Illingworth <
stephen.illingwo...@gmail.com> wrote:

> Hi Steve,
>
> What's the compiler error that you're seeing?
>
> Here's a go playground example of your scenario. It doesn't seem to cause
> any issues but maybe I'm misunderstanding.
>
> https://go.dev/play/p/vvtrQTl7FSr
>
> Regards, Stephen
>
> On Thursday, 27 July 2023 at 16:04:19 UTC+1 Steve Roth wrote:
>
>> The ongoing Go survey asked a question about satisfaction with error
>> handling in Go.  I'd like to express an opinion on it that I haven't seen
>> elsewhere, for which there was not room in the survey.
>>
>> I am generally a fan of the explicit error handling code in Go, but I get
>> frustrated by the interactions between error handling, := assignments, and
>> compiler warnings.  My preferred way of writing the standard clause is
>>
>> if err := fn(); err != nil {
>>
>> // handle error and bail out
>> }
>>
>>
>> However, often the function in question returns a result I want to work
>> with.  If it's something important for the whole rest of the function, I'll
>> probably just define it as a variable at function scope:
>>
>> var (
>>
>> result sometype
>>
>> err error
>> )
>> // ...
>>
>> if result, err = fn(); err != nil {
>>
>> // handle error and bail out
>> }
>>
>> // act on result
>>
>>
>> But often, the result is something I'm only going to use for one
>> statement and is not a variable of significance to the whole function.
>> Those are the sorts of cases that := is best for, in my opinion.  In those
>> cases, what I'd like to write is
>>
>> if result, err := fn(); err != nil {
>>
>> // handle error and bail out
>>
>> } else {
>>
>> // act on result
>> }
>>
>>
>> Unfortunately, the compiler gives a warning on that.  Because the truth
>> clause bailed out (e.g., "return"), it insists that I remove the else and
>> turn the code into
>>
>> if result, err := fn(); err != nil {
>>
>> // handle error and bail out
>>
>> }
>>
>> // act on result
>>
>>
>> But that doesn't compile because result is no longer in scope.
>>
>> What I often wind up doing instead is
>>
>> if result, err = fn(); err == nil {
>>
>> // act on result
>>
>> } else {
>>
>> // handle error and bail out
>> }
>>
>>
>> That works, but it leaves my code with a mixture of "handle error case
>> first, then success" and "handle success case first, then error" patterns,
>> which I find adds a lot to cognitive load.
>>
>> I have no idea whether others share my frustration on this admittedly
>> minor point.  But since the survey prodded me, I thought I would voice it
>> and see what reactions it gets.  For me, the ideal solution would be to
>> suppress the compiler warning about removing the else, when doing so would
>> break the code altogether.
>>
>> Regards,
>> Steve
>>
>> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts+unsubscr...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/golang-nuts/3a98bae6-8ca9-49d4-8a32-c95ae8863baen%40googlegroups.com
> 
> .
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/CAEkBMfEG8its5mq2mkJguhRNhGFh%2BPfbm7a2FBQQPq0uJT%2Bq0w%40mail.gmail.com.


[go-nuts] Re: error handling thoughts

2023-07-27 Thread Stephen Illingworth
Hi Steve,

What's the compiler error that you're seeing?

Here's a go playground example of your scenario. It doesn't seem to cause 
any issues but maybe I'm misunderstanding.

https://go.dev/play/p/vvtrQTl7FSr

Regards, Stephen

On Thursday, 27 July 2023 at 16:04:19 UTC+1 Steve Roth wrote:

> The ongoing Go survey asked a question about satisfaction with error 
> handling in Go.  I'd like to express an opinion on it that I haven't seen 
> elsewhere, for which there was not room in the survey.
>
> I am generally a fan of the explicit error handling code in Go, but I get 
> frustrated by the interactions between error handling, := assignments, and 
> compiler warnings.  My preferred way of writing the standard clause is
>
> if err := fn(); err != nil {
>
> // handle error and bail out
> }
>
>
> However, often the function in question returns a result I want to work 
> with.  If it's something important for the whole rest of the function, I'll 
> probably just define it as a variable at function scope:
>
> var (
>
> result sometype
>
> err error
> )
> // ...
>
> if result, err = fn(); err != nil {
>
> // handle error and bail out
> }
>
> // act on result
>
>
> But often, the result is something I'm only going to use for one statement 
> and is not a variable of significance to the whole function.  Those are the 
> sorts of cases that := is best for, in my opinion.  In those cases, what 
> I'd like to write is
>
> if result, err := fn(); err != nil {
>
> // handle error and bail out
>
> } else {
>
> // act on result
> }
>
>
> Unfortunately, the compiler gives a warning on that.  Because the truth 
> clause bailed out (e.g., "return"), it insists that I remove the else and 
> turn the code into
>
> if result, err := fn(); err != nil {
>
> // handle error and bail out
>
> }
>
> // act on result
>
>
> But that doesn't compile because result is no longer in scope.
>
> What I often wind up doing instead is
>
> if result, err = fn(); err == nil {
>
> // act on result
>
> } else {
>
> // handle error and bail out
> }
>
>
> That works, but it leaves my code with a mixture of "handle error case 
> first, then success" and "handle success case first, then error" patterns, 
> which I find adds a lot to cognitive load.
>
> I have no idea whether others share my frustration on this admittedly 
> minor point.  But since the survey prodded me, I thought I would voice it 
> and see what reactions it gets.  For me, the ideal solution would be to 
> suppress the compiler warning about removing the else, when doing so would 
> break the code altogether.
>
> Regards,
> Steve
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/3a98bae6-8ca9-49d4-8a32-c95ae8863baen%40googlegroups.com.


[go-nuts] Re: Error Handling

2023-02-12 Thread Harri L
A package err2  helps you to implement the 
`errReturn` even though Go doesn't have macros or can return from the 
function enclosing the function checking the error.
Please see the playground that does exactly that:
https://go.dev/play/p/GvXFU1LbVvs

However, I recommend you to use `err2` with all of its power, i.e., 
automation. Could you look at the following playground? Even the error 
strings/messages are autogenerated from function names (yeah, localization, 
but in most cases, enough to start with). Declarative error handling helps 
to keep your code safe.
https://go.dev/play/p/6Ky5nMtqu4F

And yes, I'm the author of the err2.
On Tuesday, February 7, 2023 at 11:38:41 PM UTC+2 Rich wrote:

> In most of my code I create a function to handle errors. looks something 
> like this:
>
> func errorHandle(err error, str string, ex bool) {
>  if err != nil {
>   fmt.Printf("error: %s -- %v\n",str, err)
>  }
>  if ex {
> os.Exit(1)
>  }
> }
>
> This cleans up my code:
> inFile, err := os.ReadFile("Mydata.txt")
> errorHandle(err,"read mydata.txt",true) // The true will exit
>
> So you see that I can exit the program when there is an error, what I want 
> to know is if it's possible to do the same thing inside a function, to 
> where I don't exit the program but return from the function:
>
> func OpenFile( filename string) []byte {
> inFile,err := os.ReadFile(filename)
> errReturn(err, "read "+filname,true)
>
> When there is an error it would return from the OpenFile function,
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/7292381a-655f-4ded-b193-19d85e64b2d2n%40googlegroups.com.


Re: [go-nuts] Re: Error Handling Question

2022-10-24 Thread Andrew Harris
> In many cases, including in the standard libraries, there are functions 
that return errors and then accompanying functions with names like 
MustFoo() that just call Foo() and panic if there's an error.

At least inside the standard lib, the uses of MustXxx document why they 
behave the way they do. I think the language could be written something 
like "this package considers any error in constructing a template to be a 
severe error that necessitates panic", or "... to be a runtime exception" 
without changing the reasoning about why that behavior has been chosen.

On Monday, October 24, 2022 at 5:38:22 AM UTC-7 ren...@ix.netcom.com wrote:

> Dan,
>
> If it walks like a duck…
>
> You make a great case why Go should have checked exceptions. If anything 
> the Go error handling model tries to be checked exceptions - every error 
> should be explicitly handled - without any of the conveniences of 
> exceptions - common blocks, stack traces and call stack unwinding.  
>
> On Oct 24, 2022, at 4:52 AM, Harri L  wrote:
>
> Hi,
>
>
> On Friday, October 21, 2022 at 12:14:52 AM UTC+3 dple...@google.com wrote:
>
>>
>> var x0 float
>> try {
>>x0 = check DoSomeMath(check FetchSomething(), check ComputeSomething())
>> } handle err {
>>log.Info("Unable to estimate initial approximation, defaulting to 
>> 1...")
>>x0 = 1
>> }
>> // code continues and does things with x
>>
>  
> I wanted to show what the previous block looks like with the help of the 
> current Go and some help from the err2 
> -package 
> (I'm the author). The Go playground .
>
>  calcSomething := func() (x0 int) {
> defer err2.Catch(func(err error) {
> log.Printf("Unable to estimate initial approximation: %v, 
> defaulting to 1...", err)
> x0 = 1
> })
> return try.To1(DoSomeMath(try.To1(FetchSomething()), 
> try.To1(ComputeSomething(
> }
> x0 := calcSomething()
>
> Of course, that's not exactly what you are proposing:
>
> This makes it easy to see what error handling will happen at any point 
>> within the function, keeps the control flow linear (so that, unlike 
>> defer()-based recovery, you don't have to skip ahead in the function to get 
>> context before the handler makes sense - the context comes first, followed 
>> by the handling code), and allows code to recover from errors without 
>> aborting an entire function.
>>
>  
> I also wanted to say that the `defer` -based error handling isn't so bad 
> when you are used to the defer keyword already in the Go. 
>
> Best Regards,
> -Harri
>
> -- 
>
> You received this message because you are subscribed to the Google Groups 
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to golang-nuts...@googlegroups.com.
>
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/golang-nuts/1d1e051d-4485-4fe0-a9c8-16afdc5d80e6n%40googlegroups.com
>  
> 
> .
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/9bd8c9f2-de2c-416f-bef1-f909aeaa5b84n%40googlegroups.com.


Re: [go-nuts] Re: Error Handling Question

2022-10-24 Thread Robert Engels
Dan,

If it walks like a duck…

You make a great case why Go should have checked exceptions. If anything the Go 
error handling model tries to be checked exceptions - every error should be 
explicitly handled - without any of the conveniences of exceptions - common 
blocks, stack traces and call stack unwinding.  

> On Oct 24, 2022, at 4:52 AM, Harri L  wrote:
> 
> Hi,
> 
>>> On Friday, October 21, 2022 at 12:14:52 AM UTC+3 dple...@google.com wrote:
>>> 
>>> var x0 float
>>> try {
>>>x0 = check DoSomeMath(check FetchSomething(), check ComputeSomething())
>>> } handle err {
>>>log.Info("Unable to estimate initial approximation, defaulting to 1...")
>>>x0 = 1
>>> }
>>> // code continues and does things with x
>>  
>> I wanted to show what the previous block looks like with the help of the 
>> current Go and some help from the err2-package (I'm the author). The Go 
>> playground.
>> 
>>  calcSomething := func() (x0 int) {
>> defer err2.Catch(func(err error) {
>> log.Printf("Unable to estimate initial approximation: %v, 
>> defaulting to 1...", err)
>> x0 = 1
>> })
>> return try.To1(DoSomeMath(try.To1(FetchSomething()), 
>> try.To1(ComputeSomething(
>> }
>> x0 := calcSomething()
>> 
>> Of course, that's not exactly what you are proposing:
>> 
>> This makes it easy to see what error handling will happen at any point 
>> within the function, keeps the control flow linear (so that, unlike 
>> defer()-based recovery, you don't have to skip ahead in the function to get 
>> context before the handler makes sense - the context comes first, followed 
>> by the handling code), and allows code to recover from errors without 
>> aborting an entire function.
>  
> I also wanted to say that the `defer` -based error handling isn't so bad when 
> you are used to the defer keyword already in the Go. 
> 
> Best Regards,
> -Harri
> -- 
> You received this message because you are subscribed to the Google Groups 
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to golang-nuts+unsubscr...@googlegroups.com.
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/golang-nuts/1d1e051d-4485-4fe0-a9c8-16afdc5d80e6n%40googlegroups.com.

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/69E919A4-6F98-49D5-83A4-520D2FCC12F0%40ix.netcom.com.


[go-nuts] Re: Error Handling Question

2022-10-24 Thread Harri L
Hi,

On Friday, October 21, 2022 at 12:14:52 AM UTC+3 dple...@google.com wrote:

>
> var x0 float
> try {
>x0 = check DoSomeMath(check FetchSomething(), check ComputeSomething())
> } handle err {
>log.Info("Unable to estimate initial approximation, defaulting to 1...")
>x0 = 1
> }
> // code continues and does things with x
>
 
I wanted to show what the previous block looks like with the help of the 
current Go and some help from the err2 -package 
(I'm the author). The Go playground .

 calcSomething := func() (x0 int) {
defer err2.Catch(func(err error) {
log.Printf("Unable to estimate initial approximation: %v, 
defaulting to 1...", err)
x0 = 1
})
return try.To1(DoSomeMath(try.To1(FetchSomething()), 
try.To1(ComputeSomething(
}
x0 := calcSomething()

Of course, that's not exactly what you are proposing:

This makes it easy to see what error handling will happen at any point 
> within the function, keeps the control flow linear (so that, unlike 
> defer()-based recovery, you don't have to skip ahead in the function to get 
> context before the handler makes sense - the context comes first, followed 
> by the handling code), and allows code to recover from errors without 
> aborting an entire function.
>
 
I also wanted to say that the `defer` -based error handling isn't so bad 
when you are used to the defer keyword already in the Go. 

Best Regards,
-Harri

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/1d1e051d-4485-4fe0-a9c8-16afdc5d80e6n%40googlegroups.com.


[go-nuts] Re: [error handling] RFC 'else'

2020-12-03 Thread Viktor Kojouharov
Also a lot of the proposals listed in the `Wrapping` section of 
https://seankhliao.com/blog/12020-11-23-go-error-handling-proposals/
On Wednesday, December 2, 2020 at 9:30:24 PM UTC+1 seank...@gmail.com wrote:

> see also
>
> https://github.com/golang/go/issues/41908
> https://github.com/golang/go/issues/37243
> https://github.com/gooid/gonotes/blob/master/inline_style_error_handle.md
>
> On Wednesday, December 2, 2020 at 8:57:13 PM UTC+1 Oliver Smith wrote:
>
>> Do I understand correctly that "last return value is error" is purely 
>> convention and there is no formal error handling in current go?
>>
>> My instinct is to leverage the 'else' keyword along with the notion of a 
>> "stock error whose return list's last element is type error with value != 
>> nil.
>>
>>   func not_stock() (int, interface{})
>>   func stock() error
>>   func stock() (int, error, string, float, error, error, error)
>>   func not_stock() (error, error, error, int)
>>   func stock() (error, error)
>>
>> Any other type of error handling can still be handled as the user wishes, 
>> stock errors simply provide syntax to lean into, and that syntax would be: 
>>  
>> [  ]  ast.ELSE 
>>
>> e.g.
>>
>> file, err := io.Open(file) else {
>>   return nil, err
>> }
>> fh.Close() else {
>>   panic("close call failed")
>> }
>>
>> Equivalent to:
>>
>> file, err := io.Open(file)
>> if err != nil {
>>   return nil, err
>> }
>> if err := fh.Close(); err != nil {
>>   panic("close call failed")
>> }
>>
>> One of the current nuisances of error handling is that it can break the 
>> clean flow of variable assignments, forcing you to add separate 
>> declarations or scopes. Given a function
>>
>>func NewStruct() (s *Struct, sz int, err error)
>>
>> you typically have two very different lifespans for the return values
>>
>>s, sz, err := NewStruct()
>>if err != nil {  // last reference to err in function
>>
>> vs
>>
>> if s, sz, err := NewStruct(); err != nil {
>>   panic(err)
>> } else {
>>   // to access s and sz
>> }
>>
>> or
>>
>> var (
>>   s *Struct
>>   sz int
>>   err error   // but literally only for one line
>> )
>> if s, sz, err = NewStruct(); err != nil {
>>   panic(err)
>> }
>>
>> Using the else construct always allows the shorter form, which is at 
>> least consistent:
>>
>> // not a sub-clause so s, sz and err introduced in current scope 
>> level.
>> s, sz, err := NewStruct() else {
>>   panic(err)
>> }
>>
>> The fly in the ointment here is ... where does the error go if you don't 
>> mention it?
>>
>> fh.Close() else {
>>   panic(?what?)
>> }
>>
>> the lazy option would be `_`
>>
>> fh.Close() else {
>>   fmt.Errorf("unexpected close failure: %s", _)
>>   err := _
>>   panic(err)
>> }
>>
>> But I think we can avoid the path of perl, and simply require capture if 
>> you want the value surfaced.
>>
>> err := fh.Close() else {
>>   panic(err)
>> }
>>
>>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/8930f687-b52b-4013-852f-f40c36a6fc58n%40googlegroups.com.


[go-nuts] Re: [error handling] RFC 'else'

2020-12-02 Thread seank...@gmail.com
see also

https://github.com/golang/go/issues/41908
https://github.com/golang/go/issues/37243
https://github.com/gooid/gonotes/blob/master/inline_style_error_handle.md

On Wednesday, December 2, 2020 at 8:57:13 PM UTC+1 Oliver Smith wrote:

> Do I understand correctly that "last return value is error" is purely 
> convention and there is no formal error handling in current go?
>
> My instinct is to leverage the 'else' keyword along with the notion of a 
> "stock error whose return list's last element is type error with value != 
> nil.
>
>   func not_stock() (int, interface{})
>   func stock() error
>   func stock() (int, error, string, float, error, error, error)
>   func not_stock() (error, error, error, int)
>   func stock() (error, error)
>
> Any other type of error handling can still be handled as the user wishes, 
> stock errors simply provide syntax to lean into, and that syntax would be: 
>  
> [  ]  ast.ELSE 
>
> e.g.
>
> file, err := io.Open(file) else {
>   return nil, err
> }
> fh.Close() else {
>   panic("close call failed")
> }
>
> Equivalent to:
>
> file, err := io.Open(file)
> if err != nil {
>   return nil, err
> }
> if err := fh.Close(); err != nil {
>   panic("close call failed")
> }
>
> One of the current nuisances of error handling is that it can break the 
> clean flow of variable assignments, forcing you to add separate 
> declarations or scopes. Given a function
>
>func NewStruct() (s *Struct, sz int, err error)
>
> you typically have two very different lifespans for the return values
>
>s, sz, err := NewStruct()
>if err != nil {  // last reference to err in function
>
> vs
>
> if s, sz, err := NewStruct(); err != nil {
>   panic(err)
> } else {
>   // to access s and sz
> }
>
> or
>
> var (
>   s *Struct
>   sz int
>   err error   // but literally only for one line
> )
> if s, sz, err = NewStruct(); err != nil {
>   panic(err)
> }
>
> Using the else construct always allows the shorter form, which is at least 
> consistent:
>
> // not a sub-clause so s, sz and err introduced in current scope level.
> s, sz, err := NewStruct() else {
>   panic(err)
> }
>
> The fly in the ointment here is ... where does the error go if you don't 
> mention it?
>
> fh.Close() else {
>   panic(?what?)
> }
>
> the lazy option would be `_`
>
> fh.Close() else {
>   fmt.Errorf("unexpected close failure: %s", _)
>   err := _
>   panic(err)
> }
>
> But I think we can avoid the path of perl, and simply require capture if 
> you want the value surfaced.
>
> err := fh.Close() else {
>   panic(err)
> }
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/db52e100-83e0-4fed-9d19-c6278d4a211fn%40googlegroups.com.


[go-nuts] Re: Error Handling Best Practice (error wrapping)

2018-10-09 Thread Henry
Hi,

There are two kinds of errors: user-facing error and developer-facing 
error. User-facing error is an error that is supposed to be relayed back to 
the end-users. It is usually stripped from sensitive information and is 
generally more verbose. On the other hand, developer-facing error are 
intended for developers. It may contain stacktraces, etc. and is generaly 
more terse.

Go's standard error implementation is very basic and unassuming about your 
intended use. However, it is also trivial to write your own error library 
(Hint: the runtime package). I usually use my own error library. So 
whenever you find that the standard error implementation does not suit your 
need, feel free to implement your own.

In addition, in designing your functions, be sure to return error 
judiciously. Consider whether returning errors provide any value to the 
callers of your functions, and whether it is sufficient to just return a 
neutral value or to panic. In general, functions that return errors are 
more difficult to use. It is easy to 'pass the buck' and just blindly send 
back any error to the caller. In the end, at the top layer of the 
application, you end up with way too many error checking code. So, return 
error judiciously.

Some people think that using exceptions will help solve this problem. 
Exceptions merely hide the symptoms (eg. fewer error checking code), but it 
doesn't cure the problem, which is a poorly designed function interface. In 
fact, exceptions carry with them their own horde of problems. You have 
checked and unchecked exceptions. Some people prefer one to the other. Java 
has both, while the C# team considers checked exceptions does not bring any 
value to their existing problems. Then, you have versioning and scalability 
issue, etc.

Go's error handling is not perfect, but it is simple and thus any 
associated problems surrounding it are also easy to understand. 

On Monday, October 8, 2018 at 5:38:09 PM UTC+7, Chris Hopkins wrote:
>
> Hi,
> Could I please check what current error handling best practice is?
> I've gotten quite smitten with github.com/pkg/errors. I really like the 
> ability to create a stack of errors that trace to what is going on. However 
> it seems this is not an often used package - it's not available in 
> playground for example. It's really useful for diagnostics to see a stack 
> of what is causing an error, however in my latest application where I'm 
> trying to be really rigorous with my error handling I've hit - for want of 
> a better word - an imperfection. Could I check if there's a better way to 
> do these things:
> So here's what I'm doing:
> When I have an error I need to report I create it like this:
> var ErrInvalidVariable = errors.New("Invalid Variable")
> Which means that you can have code that nicely reads: 
> if err == ErrInvalidVariable { /* handle this error */}
> It's how the os package reports errors (along with helper functions), so I 
> assume this is the correct way.
>
>
> For better debug I can use errors.Wrap to annotate this error through the 
> error stack and get useful diagnostic printouts such as
> Line Processing passed "if $BOB==3": Token Passed $BOB : Invalid Variable.
>
> So far so good. This starts to fail though if I'm trying to determine lets 
> say a fileio error that came from the config file reader, vs the script 
> file reader. At the moment I can say
> _, err := os.Open(...)
> if err != nil {
>   return errors.Wrap(err, "Config File read error")
> }
> But without searching through the error text I can't tell who caused that.
> Now I could declare a specific type for this, add a Cause handler onto 
> that, but it starts to get clunky to do that for every error condition. 
> Also it doesn't scale to more than 2 levels because it stops at the first 
> cause found. I can obviously work around this, but I'm thinking I'm doing 
> this wrong, a defining feature of go is the error handling - surely there's 
> a better way to do it than this!.
>
> Am I doing something unusual here and wanting to determine where in the 
> hierarchy of the stack a problem might have come from? How else do people 
> handle errors in situations like this, where you can't fully handle them 
> locally, so you want to return the error, but then when you get to the 
> higher levels you can handle them, as long as you have information about 
> the error. The annoying thing is, everything is there in the string of the 
> error message and I could strings.Contains my way through the error string 
> to work this out, but that feels a really stupid way to do this.
> I also come across this in my test cases, I want to inject error to make 
> sure I am spotting errors correctly and checking that I am getting the 
> correct error from the correct place is really quite clunky at the moment, 
> if I could test that an error checker in location X was triggered by it 
> being passed an error that would save me a lot of code.
>
> Any suggestions gratefully 

Re: [go-nuts] Re: error handling needs syntactical sugar

2017-09-11 Thread Konstantin Khomoutov
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

2017-09-11 Thread Tim Uckun
| 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

2017-09-11 Thread Konstantin Khomoutov
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

2017-09-08 Thread 'Axel Wagner' via golang-nuts
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(, "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

2017-09-08 Thread ekocjan

>
> 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(, "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

2017-09-08 Thread Dorival Pedroso
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

2017-09-08 Thread Marvin Renich
* 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

2017-09-08 Thread Wojciech S. Czarnecki
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(, "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

2017-09-08 Thread Dorival Pedroso
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

2017-09-08 Thread Dorival Pedroso
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

2017-09-07 Thread Dave Cheney

>
>
> 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

2017-09-07 Thread Dorival Pedroso
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

2017-09-07 Thread Nigel Tao
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

2017-09-07 Thread Wojciech S. Czarnecki
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

2017-09-07 Thread 'Axel Wagner' via golang-nuts
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

2017-09-07 Thread snmed
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

2017-09-07 Thread 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

2017-09-07 Thread Tamás Gulácsi
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

2017-09-07 Thread martin . rode
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

2017-09-07 Thread 'Axel Wagner' via golang-nuts
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 

[go-nuts] Re: error handling needs syntactical sugar

2017-09-07 Thread Dorival Pedroso
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

2017-09-07 Thread Tim Uckun
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 

Re: [go-nuts] Re: error handling needs syntactical sugar

2017-09-05 Thread Dorival Pedroso
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

2017-09-05 Thread Michael Jones
...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 

[go-nuts] Re: error handling needs syntactical sugar

2017-09-05 Thread Dorival Pedroso
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 

[go-nuts] Re: error handling needs syntactical sugar

2017-09-05 Thread Dorival Pedroso
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

2017-09-05 Thread Dorival Pedroso
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

2017-09-05 Thread Dorival Pedroso
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, 

[go-nuts] Re: error handling needs syntactical sugar

2017-09-05 Thread Dorival Pedroso
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 

[go-nuts] Re: error handling needs syntactical sugar

2017-09-05 Thread ekocjan
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

2017-09-05 Thread prades . marq
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 := {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 

Re: [go-nuts] Re: error handling needs syntactical sugar

2017-09-05 Thread Dorival Pedroso
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 := {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 

Re: [go-nuts] Re: error handling needs syntactical sugar

2017-09-05 Thread Dorival Pedroso
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

2017-09-05 Thread Rob Pike
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

2017-09-05 Thread Dorival Pedroso
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

2017-09-05 Thread martin . rode
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

2017-09-05 Thread Dorival Pedroso
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

2017-09-05 Thread martin . rode
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

2017-09-05 Thread martin . rode

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

2017-09-04 Thread Dorival Pedroso
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

2017-09-04 Thread Dorival Pedroso
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

2017-09-04 Thread Dorival Pedroso
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 

[go-nuts] Re: error handling needs syntactical sugar

2017-09-04 Thread Dorival Pedroso
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.


[go-nuts] Re: Error handling best practices and unit testing complex error values

2017-04-06 Thread Henry
Use dependency injection and mock the objects to simulate the errors.

In my opinion though, there is no need for an error to hold references to 
its underlying errors. Errors are just values. You take their values, add 
any additional information, and create a new error. You shouldn't need to 
test whether the error contains any specific underlying error. The point of 
'wrapping' error is to prevent access to the underlying errors. I will show 
some examples:

Given you have the following layers: presentation->domain->data. Let's say 
a user attempts to sign in with an invalid username. The data layer checks 
with the database and finds out that there is no such user. So the data 
layer component returns data.ErrMissingUser. Upon receiving the error, the 
domain layer takes the data.ErrMissingUser's error message, adds any 
additional information, and returns a new error domain.ErrInvalidUser to 
the presentation layer. For testing the domain layer component, mock the 
data component and simulate it to return the data.ErrMissingUser. Then in 
your test, check whether the domain component returns domain.ErrInvalidUser.

When dealing with non-predefined errors, let's say there is a database 
error, the data layer returns the error to the domain layer. The domain 
layer takes the error message, adds any additional information, and creates 
a new error. When testing the domain layer, mock the data component and 
have it return an error. Then, in your test, ensure that the domain 
component returns an error. 

Different people may have different approach to this.


On Wednesday, April 5, 2017 at 7:29:24 PM UTC+7, jlb1...@gmail.com wrote:

> Let's say I have an app with three layers: a view (JSON endpoint), 
> service, and persistence layer.
>
>
> Now a `NotFoundError` error occurs at the persistence layer when a record 
> cannot be found. `NotFoundError` is a simple wrapper around a lower level 
> database driver error that I don't want the application to be aware of 
> (since it's an implementation detail).
>
>
> For example, if the `gocql` driver emits an `ErrNotFound` error, the 
> persistence layer will wrap it in a custom error type so that the original 
> error is preserved but not exposed.
>
>
> package database
>
> type NotFoundError struct {
>   originalErr error // persistence layer wraps the driver error
> }
>
>
>
> The service layer then type switches on whatever errors it receives from 
> lower layers. For example in a call to the persistence layer:
>
>
>
> package service
>
> func (s *Service) GetSomething(id string) (string, error) {
>   s, err := database.Get(id)
>   if err != nil {
> return "", handleError(err, “service: failed to get something”)
>   }
> }
>
>
> func handleError(err error, context, message string) error {
>   switch err.(type) {
> case database.NotFoundError:
>   return {
> Code: NotFoundCode,
> Message: message,
> originalErr: errors.Wrap(err, context),
>   }
> default:
>  ...
>   }
> }
>
>
>
> a service error is a custom error type that looks like:
>
>
> type ServiceError struct {
>  originalErr error
>  Codeint `json:"code"`
>  Field string`json:"target,omitempty"`
>  Message string  `json:"message,omitempty"`
>  Details []*ServiceError `json:"details,omitempty"`
> }
>
>
>
>
> To recap, the error propagates through the following layers:
>
>
> driver -> persistence -> service -> view
>
>
> Each layer type switches on the error type it receives from the preceding 
> layer. 
>
> Errors may be recursively nested (the "Details" field is a 
> []*ServiceError) and "originalErr" contains the original error with a stack 
> trace provided by the pkg/errors  library.
>
>
> How would one approach unit testing something like this? 
>
>
> Doing a simple reflect.DeepEqual on the actual and expected error values 
> would be ideal, but the stack trace contained in the actual error means 
> that the expected error will always fail the equality comparison (since 
> DeepEqual also parses unexported fields). In addition, the order of errors 
> in the `Details` slice is also unreliable (for example when validating 
> fields, the order shouldn't matter) which further complicates trying to 
> compare things. I’d have to pollute my tests with loops, manual comparisons 
> and recursive logic which will itself be error-prone.
>
>
> I’ve looked through some popular projects on GitHub and I can’t find any 
> examples of code similar to this this which leads me to believe that all 
> these abstraction hierarchies and complex errors types are horribly 
> unidiomatic Go... I now know why people say Go is more of a systems 
> language. But anyway... is there a better way to deal with errors in an app 
> structured like this? How would you go about comparing these types of error 
> values? How do you handle rich errors types with lots of contextual 
> information in your own web applications?

[go-nuts] Re: Error Handling

2016-11-26 Thread Christophe Meessen
Just for clarification, the function fn() must return an interface for this to 
work. 

-- 
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

2016-11-25 Thread Dave Cheney
Would a type switch do what you want ?

err := fn()
switch err := err.(type) {
case nil:
   // all good
case *MyCustomError:
   // do something custom
default:
   // unexpected error
}

On Saturday, 26 November 2016 05:07:55 UTC+11, Parveen Kumar wrote:
>
> Hi Team,
>
> I want to catch my custom error being returned from various methods and 
> based on their type i want to return http error code. is ther any generic 
> way?
>
> Regards,
> Parveen Kumar
>

-- 
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 and structured logging

2016-10-15 Thread Jolie Rouge
At first I didn't like this idea, but the README has converted me to the 
possibilities. I have to admit I have a strong aversion to interface{}, and 
a map as well, but a lot of the other features are very interesting. I 
think, in a larger project, this may be just the thing for structured 
logging, though I tend to roll my own.

The single mindedness of errors in go is actually something good IMHO, 
though sometimes we'd like to stick more data in, is errors.With("blah", 
"blah").Wrap(other_error) Really different than 
errors.New(fmt.Sprintf("blah=blah because %s",other_err))? I guess it seems 
more pleasing to use a fluid interface if you come to go from a language 
that emphasized that, but sometimes the ease of writing occludes the ease 
of reading, or reasoning. Also - who has time to learn Yet Another Library.

Yet in a large application, say an API or some kind of webservice, 
structured logging and a logging/error API not only has a place, but would 
be a boon to the project all. I think it's a great addition to the 
ecosystem, and good as a tool for people to use if and when they need it. I 
know I'll give it a go on my next project that is a webservice, so this 
might be just the thing...

/Jason

Le mercredi 12 octobre 2016 05:34:48 UTC+2, John Jeffery a écrit :
>
> I have been following the progress of package github.com/pkg/errors, and 
> have put it to much use. Thanks very much to Dave Cheney and the other 
> authors.
>
> A few months ago an interesting issue was raised along the lines of being 
> able to attach arbitrary data to the error (
> https://github.com/pkg/errors/issues/34). Some interesting discussion 
> ensued, and in the end Dave decided not to add this feature to the package, 
> and gave some very good reasons for his decision. This is all good and I 
> think I learned a lot from the discussion.
>
> All the same I became quite interested in the idea that, if key/value 
> pairs of information could be attached to errors as they "bubble up" the 
> stack, then this could provide an alternative to passing a logger down 
> through the call stack, adding context along the way until something 
> actually has to be logged.
>
> So given that the github.com/pkg/errors package was not going to include 
> the feature, I decided to have a go at building an errors package that 
> provides a minimal API for programs that make use of structured logging. 
> The result is at https://github.com/jjeffery/errors. The API has a very 
> small surface area, and I have found it pleasant to use in my own projects.
>
> Of course there are many other popular error handling packages, and 
> github.com/pkg/errors combines the best ideas of many of them. I think it 
> is a stated goal that github.com/pkg/errors be considered for inclusion 
> in the standard library at some point. I just have not seen structured 
> key/values integrated into error handling in quite the same way before, and 
> thought I'd mention this work and ask for community feedback.
>
>

-- 
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.