custom type wrapping errors; what am i missing?

109 views
Skip to first unread message

simon place

unread,
Sep 2, 2020, 11:44:22 AM9/2/20
to golang-nuts

simon place

unread,
Sep 2, 2020, 11:47:54 AM9/2/20
to golang-nuts

should be

import "errors"

left over from testing, but makes no difference, as expected.

burak serdar

unread,
Sep 2, 2020, 11:58:31 AM9/2/20
to simon place, golang-nuts
What were you expecting?

>
> --
> 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/0d654a7b-dc92-432b-b152-91bd6ba68cf2o%40googlegroups.com.

simon place

unread,
Sep 2, 2020, 12:04:29 PM9/2/20
to golang-nuts
the example compares the print output of a fmt.errorf wrapped error and a custom-error type wrapped error, the custom one isn't showing the wrapped error.,


On Wednesday, 2 September 2020 16:58:31 UTC+1, burak serdar wrote:
On Wed, Sep 2, 2020 at 9:48 AM 'simon place' via golang-nuts
<golan...@googlegroups.com> wrote:
>
> import "github.com/pkg/errors"
>
> should be
>
> import "errors"
>
> left over from testing, but makes no difference, as expected.

What were you expecting?

>
> --
> 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 golan...@googlegroups.com.

burak serdar

unread,
Sep 2, 2020, 12:18:10 PM9/2/20
to simon place, golang-nuts
On Wed, Sep 2, 2020 at 10:05 AM 'simon place' via golang-nuts
<golan...@googlegroups.com> wrote:
>
> the example compares the print output of a fmt.errorf wrapped error and a custom-error type wrapped error, the custom one isn't showing the wrapped error.,

It will if you also print the wrapped error:

func (e MyErr) Error() string {
return "My wrapping:"+ e.error.Error()
}



>
> On Wednesday, 2 September 2020 16:58:31 UTC+1, burak serdar wrote:
>>
>> On Wed, Sep 2, 2020 at 9:48 AM 'simon place' via golang-nuts
>> <golan...@googlegroups.com> wrote:
>> >
>> > import "github.com/pkg/errors"
>> >
>> > should be
>> >
>> > import "errors"
>> >
>> > left over from testing, but makes no difference, as expected.
>>
>> What were you expecting?
>>
>> >
>> > --
>> > 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 golan...@googlegroups.com.
>> > To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/0d654a7b-dc92-432b-b152-91bd6ba68cf2o%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...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/d240fe1d-fce5-41c5-b45e-03bb5caa9e9eo%40googlegroups.com.

Jake Montgomery

unread,
Sep 2, 2020, 12:22:19 PM9/2/20
to golang-nuts
I think you may be confused about fmt and error unwrapping.

The fmt.Println() in your example code does not unwrap err1. When fmt.Errorf creates the error, the message  is hard coded "fmt wrapping: error". The Println is just printing the result of err1.Error()

simon place

unread,
Sep 2, 2020, 12:30:54 PM9/2/20
to golang-nuts
my understanding is the whole wrap mechanism is to move to types, rather than strings, so you can test for a 'class' of error without the hacky use of string comparison.

On Wednesday, 2 September 2020 17:18:10 UTC+1, burak serdar wrote:
On Wed, Sep 2, 2020 at 10:05 AM 'simon place' via golang-nuts
<golan...@googlegroups.com> wrote:
>
> the example compares the print output of a fmt.errorf wrapped error and a custom-error type wrapped error, the custom one isn't showing the wrapped error.,

It will if you also print the wrapped error:

func (e MyErr) Error() string {
   return "My wrapping:"+ e.error.Error()
}



>
> On Wednesday, 2 September 2020 16:58:31 UTC+1, burak serdar wrote:
>>
>> On Wed, Sep 2, 2020 at 9:48 AM 'simon place' via golang-nuts
>> <golan...@googlegroups.com> wrote:
>> >
>> > import "github.com/pkg/errors"
>> >
>> > should be
>> >
>> > import "errors"
>> >
>> > left over from testing, but makes no difference, as expected.
>>
>> What were you expecting?
>>
>> >
>> > --
>> > 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 golan...@googlegroups.com.
>> > To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/0d654a7b-dc92-432b-b152-91bd6ba68cf2o%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 golan...@googlegroups.com.

burak serdar

unread,
Sep 2, 2020, 12:35:35 PM9/2/20
to simon place, golang-nuts
On Wed, Sep 2, 2020 at 10:31 AM 'simon place' via golang-nuts
<golan...@googlegroups.com> wrote:
>
> my understanding is the whole wrap mechanism is to move to types, rather than strings, so you can test for a 'class' of error without the hacky use of string comparison.

You do that using errors.Is and errors.As that use the Unwrap method
to descend the error chain. Error() simply returns a string
representation of the error.
> 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/844c4220-5e2a-466f-8a9d-63904fd11e89o%40googlegroups.com.

simon place

unread,
Sep 2, 2020, 2:19:31 PM9/2/20
to golang-nuts
OK, i think i have it;

basically he root of it was i wasn't thinking properly about how errors need/should be implemented as immutable. Unwrap is basically a state getter. (no setter for the wrapped error.)

so it seems to me that custom and fmt.Prinf("%w") wrappers have different use cases:

* fmt.Printf(%w) is just to add more text to an error, because errors are immutable its needed.(unless you have custom error types and are local to them, then you could just edit their state.)

* custom wrapping types, unlike fmt.Printf(%w), create error 'classes' for testing against and have utilities to help deal with unknown depths of wrapping.

since i was only dealing with one level, i probably should have avoided wrapping entirely, but now i know!

this does seem as if its a pattern that might come up elsewhere, so good to understand clearly (unless i'm still off about something above).

thanks for help.

burak serdar

unread,
Sep 2, 2020, 2:38:19 PM9/2/20
to simon place, golang-nuts
On Wed, Sep 2, 2020 at 12:20 PM 'simon place' via golang-nuts
<golan...@googlegroups.com> wrote:
>
> OK, i think i have it;
>
> basically he root of it was i wasn't thinking properly about how errors need/should be implemented as immutable. Unwrap is basically a state getter. (no setter for the wrapped error.)
>
> so it seems to me that custom and fmt.Prinf("%w") wrappers have different use cases:

%w is not a formatting verb, so fmt.Prinf("%w") is not valid.

Instead of creating a separate MyErr struct, you could've done:

err1:= errors.New("error")
err1= fmt.Errorf("fmt wrapping: %w",err1)
fmt.Println(err1)

err2:=errors.New("error")
err3= fmt.Errorf("Wrapped: %w",err2)
// Here, err3 is an error wrapping err2
fmt.Println(err3)


>
> * fmt.Printf(%w) is just to add more text to an error, because errors are immutable its needed.(unless you have custom error types and are local to them, then you could just edit their state.)
>
> * custom wrapping types, unlike fmt.Printf(%w), create error 'classes' for testing against and have utilities to help deal with unknown depths of wrapping.
>
> since i was only dealing with one level, i probably should have avoided wrapping entirely, but now i know!
>
> this does seem as if its a pattern that might come up elsewhere, so good to understand clearly (unless i'm still off about something above).
>
> thanks for help.
>
> --
> 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/fa0e1186-c185-4143-9df9-d0ba7aa11826o%40googlegroups.com.

simon place

unread,
Sep 2, 2020, 2:59:40 PM9/2/20
to golang-nuts
%w is not a formatting verb, so fmt.Prinf("%w") is not valid. 

yes, i thought i was pasting fmt.Errorf("%w",err)

err1:= errors.New("error")
err1= fmt.Errorf("fmt wrapping: %w",err1)
fmt.Println(err1)

err2:=errors.New("error")
err3= fmt.Errorf("Wrapped: %w",err2)
// Here, err3 is an error wrapping err2
fmt.Println(err3)

i was trying to create a error 'class', i now realise fmt.Errorf isn't capable/for that. i thought all wrapping was 'grouping' i now see another use case that this handles. it was the two uses that confused me.

Jake Montgomery

unread,
Sep 3, 2020, 8:34:30 AM9/3/20
to golang-nuts
On Wednesday, September 2, 2020 at 2:19:31 PM UTC-4, simon place wrote:


 * fmt.Printf(%w) is just to add more text to an error, because errors are immutable its needed.(unless you have custom error types and are local to them, then you could just edit their state.)

There is more to  fmt.Errorf(%w) than " just to add more text". Sure, it creates static error text that contains the wrapped error's text. But it also creates a true wrapped error. See https://play.golang.org/p/EH-XoZGneMj

If you have not already, I suggest reading https://blog.golang.org/go1.13-errors
Reply all
Reply to author
Forward
0 new messages