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&D
> 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(&err) r :=
> try.To1(os.Open(src)) defer r.Close() w := try.To1(os.Create(dst)) defer
> err2.Handle(&err, 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&D 
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(&err) r := 
try.To1(os.Open(src)) defer r.Close() w := try.To1(os.Create(dst)) defer 
err2.Handle(&err, 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

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 {
>> panic(err)

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

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 err

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

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 e

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 

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 the

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? (Again

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.


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.


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(&MT, "ABA","SC","RSN") shape).
>>
>> For SQL call chains you may use "For/Switch" pattern:
>> https://play.golang.org/p/0gWarQ8TL7 .
>>
>> For/Switch is clear and can cope with e.g. retries for a 5 lines more:
>> https://play.golang.org/p/CyhIJabzFn
>>
>> watch:
>> for i = 1; retry < 3; i++ {
>> if err != nil {
>> i--
>> retry++
>> continue
>> }
>> switch i {
>> case 1:
>> err = getData(i)
>> case 2:
>> err = getData(i)
>> case 3:
>> err = getData(i)
>> default:
>> break watch
>> }
>> }
>> if err != nil {
>> // handle common error
>> }
>>
>> All above patterns have single err handling place yet give back
>> information
>> where err was set -- something "watch" knows nothing about.
>>
>> P.S. someone else proposed wrapper with error handling in defer.
>> IMO it is as bad as watch - spooky, at distance, clunky.
>>
>> --
>> Wojciech S. Czarnecki
>>  << ^oo^ >> OHIR-RIPE
>>
> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


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

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(&MT, "ABA","SC","RSN") shape). 
>
> For SQL call chains you may use "For/Switch" pattern: 
> https://play.golang.org/p/0gWarQ8TL7 . 
>
> For/Switch is clear and can cope with e.g. retries for a 5 lines more: 
> https://play.golang.org/p/CyhIJabzFn 
>
> watch: 
> for i = 1; retry < 3; i++ { 
> if err != nil { 
> i-- 
> retry++ 
> continue 
> } 
> switch i { 
> case 1: 
> err = getData(i) 
> case 2: 
> err = getData(i) 
> case 3: 
> err = getData(i) 
> default: 
> break watch 
> } 
> } 
> if err != nil { 
> // handle common error 
> } 
>
> All above patterns have single err handling place yet give back 
> information 
> where err was set -- something "watch" knows nothing about. 
>
> P.S. someone else proposed wrapper with error handling in defer. 
> IMO it is as bad as watch - spooky, at distance, clunky. 
>
> -- 
> Wojciech S. Czarnecki 
>  << ^oo^ >> OHIR-RIPE 
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


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

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(&MT, "ABA","SC","RSN") shape).

For SQL call chains you may use "For/Switch" pattern:
https://play.golang.org/p/0gWarQ8TL7 .

For/Switch is clear and can cope with e.g. retries for a 5 lines more:
https://play.golang.org/p/CyhIJabzFn

watch:
for i = 1; retry < 3; i++ {
if err != nil {
i--
retry++
continue
}
switch i {
case 1:
err = getData(i)
case 2:
err = getData(i)
case 3:
err = getData(i)
default:
break watch
}
}
if err != nil {
// handle common error
}

All above patterns have single err handling place yet give back information
where err was set -- something "watch" knows nothing about.

P.S. someone else proposed wrapper with error handling in defer.
IMO it is as bad as watch - spooky, at distance, clunky. 

-- 
Wojciech S. Czarnecki
 << ^oo^ >> OHIR-RIPE

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


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

2017-09-07 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-07 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 an error
>> ctx.Se

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 is actually happenin

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 := &errWriter{w: fd}
> ew.write(p0[a:b])
> ew.write(p1[c:d])
> ew.write(p2[e:f])
> // and so on
> if ew.err != nil {
> return ew.err
> }
>
>
> could easily (?, I don't know) be replaced by:
>
> *watch* err != nil {
>
> return err
>
> }
> err = fd.write(p0[a:b])
> err = fd.write(p1[c:d])
> err = fd.write(p2[e:f])
> // and so on
>
>
> and we wouldn't need the wrapping structure... (sorry for being so lazy ;-)
>
> By the way, maybe one day I'll attend a GoCon and will bring a laptop for 
> sure...
>
> Cheers.
> Dorival
>
>
> On Tuesday, September 5, 2017 at 6:39:05 PM UTC+10, Rob 'Commander' Pike 
> wrote:
>>
>> If you find that lines like if err != nil are a significant fraction 
>> of non-test code, your code probably needs a better error handling 
>> strategy, not a language change. I have done measurements in the past 
>> and although people complain a lot about the presence of that 
>> statement, it shows up much less often in practice than people claim, 
>> and when it does appear a lot it's usually because the programmer is 
>> not thinking enough about how errors should work. 
>>
>> Please reread that blog post. 
>>
>> -rob 
>>
>>
>> On Tue, Sep 5, 2017 at 5:45 PM, Dorival Pedroso  
>> wrote: 
>> > Fair enough. This would be perfect. Cheers 
>> > 
>> > 
>> > On Tuesday, September 5, 2017 at 5:42:26 PM UTC+10, 
>> > marti...@programmfabrik.de wrote: 
>> >> 
>> >> Dorival, 
>> >> 
>> >> I think we can celebrate already if we achieve anything with this 
>> >> discussion. Let's not ask for too much, plus let's not make it too 
>> >> complicated. 
>> >> 
>> >> I think your proposed "watch err", hides too much and does too little. 
>> >> 
>> >> You can simply write (the inline code editor is broken, BTW) 
>> >> 
>> >> func ... { 
>> >> var err 
>> >> watch err != nil { 
>> >> // handle error 
>> >> return 
>> >> } 
>> >> // do stuff 
>> >> yo1, err := do_stuff1() 
>> >> yo2, err := do_stuff2() 
>> >> yo3, err := do_stuff3() 
>> >> } 
>> >> 
>> >> 
>> >> Martin 
>> >> 
>> >> 
>> >> On Tuesday, September 5, 2017 at 9:32:50 AM UTC+2, Dorival Pedroso 
>> wrote: 
>> >>> 
>> >>> Hi Martin; 
>> >>> 
>> >>> What about two commands "watch" and "watchif"? 
>> >>> 
>> >>> The first works as the "var" command and the second as the "if" 
>> command. 
>> >>> 
>> >>> "watch" does: 
>> >>> 
>> >>> In a function with error as an output (anywhere): returns in case the 
>> err 
>> >>> declared with watch err (or watch myerror) becomes non-nil. watch err 
>> would 
>> >>> declare err" as var does. Most use cases would put watch err at the 
>> >>> beginning of a function (although this is optional as it is with 
>> defer) 
>> >>> In a test function; aka TestSomething(something *testing.T), watch 
>> err 
>> >>> error would declare err (or watch myerror error) and if an error 
>> occurs, it 
>> >>> would call something.FailNow() after (printing the error 
>> message?---still 
>> >>> need to think this part better) 
>> >>> In the main function: watch err error would print the error message 
>> (or 
>> >>> maybe pipe to stderr) and os.Exist(1) 
>> >>> watchif err != nil {HERE} would be more powerful because it would 
>> allow 
>> >>> us to do other things. But the mechanism is similar (as you proposed 
>> >>> initially): if err becomes non-nil anywhere, the execution in HERE 
>> would 
>> >>> take place. 
>> >>> 
>> >>> Cheers! 
>> >>> 
>> >>> 
>> >>> On Tuesday, September 5, 2017 at 4:55:59 PM UTC+10, 
>> >>> marti...@programmfabrik.de wrote: 
>>  
>>  Hi Dorival, 
>>  
>>  thanks for supporting me with my idea. 
>>  
>>  And yes, after writing my post yesterday I was thinking, "watchif" 
>> or 
>>  even simply "watch". 
>>  
>>  And yes, today I am more in favor of simply "watch". 
>>

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

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 := &errWriter{w: fd}
ew.write(p0[a:b])
ew.write(p1[c:d])
ew.write(p2[e:f])
// and so on
if ew.err != nil {
return ew.err
}


could easily (?, I don't know) be replaced by:

*watch* err != nil {

return err

}
err = fd.write(p0[a:b])
err = fd.write(p1[c:d])
err = fd.write(p2[e:f])
// and so on


and we wouldn't need the wrapping structure... (sorry for being so lazy ;-)

By the way, maybe one day I'll attend a GoCon and will bring a laptop for 
sure...

Cheers.
Dorival


On Tuesday, September 5, 2017 at 6:39:05 PM UTC+10, Rob 'Commander' Pike 
wrote:
>
> If you find that lines like if err != nil are a significant fraction 
> of non-test code, your code probably needs a better error handling 
> strategy, not a language change. I have done measurements in the past 
> and although people complain a lot about the presence of that 
> statement, it shows up much less often in practice than people claim, 
> and when it does appear a lot it's usually because the programmer is 
> not thinking enough about how errors should work. 
>
> Please reread that blog post. 
>
> -rob 
>
>
> On Tue, Sep 5, 2017 at 5:45 PM, Dorival Pedroso  > wrote: 
> > Fair enough. This would be perfect. Cheers 
> > 
> > 
> > On Tuesday, September 5, 2017 at 5:42:26 PM UTC+10, 
> > marti...@programmfabrik.de wrote: 
> >> 
> >> Dorival, 
> >> 
> >> I think we can celebrate already if we achieve anything with this 
> >> discussion. Let's not ask for too much, plus let's not make it too 
> >> complicated. 
> >> 
> >> I think your proposed "watch err", hides too much and does too little. 
> >> 
> >> You can simply write (the inline code editor is broken, BTW) 
> >> 
> >> func ... { 
> >> var err 
> >> watch err != nil { 
> >> // handle error 
> >> return 
> >> } 
> >> // do stuff 
> >> yo1, err := do_stuff1() 
> >> yo2, err := do_stuff2() 
> >> yo3, err := do_stuff3() 
> >> } 
> >> 
> >> 
> >> Martin 
> >> 
> >> 
> >> On Tuesday, September 5, 2017 at 9:32:50 AM UTC+2, Dorival Pedroso 
> wrote: 
> >>> 
> >>> Hi Martin; 
> >>> 
> >>> What about two commands "watch" and "watchif"? 
> >>> 
> >>> The first works as the "var" command and the second as the "if" 
> command. 
> >>> 
> >>> "watch" does: 
> >>> 
> >>> In a function with error as an output (anywhere): returns in case the 
> err 
> >>> declared with watch err (or watch myerror) becomes non-nil. watch err 
> would 
> >>> declare err" as var does. Most use cases would put watch err at the 
> >>> beginning of a function (although this is optional as it is with 
> defer) 
> >>> In a test function; aka TestSomething(something *testing.T), watch err 
> >>> error would declare err (or watch myerror error) and if an error 
> occurs, it 
> >>> would call something.FailNow() after (printing the error 
> message?---still 
> >>> need to think this part better) 
> >>> In the main function: watch err error would print the error message 
> (or 
> >>> maybe pipe to stderr) and os.Exist(1) 
> >>> watchif err != nil {HERE} would be more powerful because it would 
> allow 
> >>> us to do other things. But the mechanism is similar (as you proposed 
> >>> initially): if err becomes non-nil anywhere, the execution in HERE 
> would 
> >>> take place. 
> >>> 
> >>> Cheers! 
> >>> 
> >>> 
> >>> On Tuesday, September 5, 2017 at 4:55:59 PM UTC+10, 
> >>> marti...@programmfabrik.de wrote: 
>  
>  Hi Dorival, 
>  
>  thanks for supporting me with my idea. 
>  
>  And yes, after writing my post yesterday I was thinking, "watchif" or 
>  even simply "watch". 
>  
>  And yes, today I am more in favor of simply "watch". 
>  
>  And yes, we can constrain this to the context of one function (like 
>  defer), I am ok with that. 
>  
>  What you are describing how you work with errors and how you spent 
> hours 
>  adding 
>  
>  if err != nil 
>  
>  that is exactly my point. 
>  
>  On could nicely write this 
>  
>  ... 
>  watch err!=nil { 
>    handle_sql_error(err) 
>  } 
>  ... 
>  
>  Of course, watch could also be used to not watch out for errors but 
> any 
>  other places where new values to get assigned to variables. 
>  
>  Martin 
> >> 
> >> 
> > -- 
> > You received this message because

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

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.