My limited understanding of Go error "kinds" is as follows:

   1. error values of arbitrary type, where the type doesn't matter: such 
   as returned by errors.New("D'OH!").
   2. sentinel(?) errors, such as io.EOF: when comparing against the same 
   error instance.
   3. wrapped errors, where the type of the wrapper (type) doesn't matter: 
   such as created by fmt.Errorf("...%w", err)
   4. ...
   
Now, in some situations I would like to use typed errors which additionally 
wrap underlying errors. Sentinel (2) errors don't work, as due to the 
wrapping there would be an open number of different values with no chance 
of classification. And (3) doesn't allow individual typing either.

In order to create individual error types that additionally wrap underlying 
one can either write the same following boilerplate over and over again, or 
alternatively use embedding in addition with method propagation. For 
instance:

type WrappingError struct {
   msg string
   err error
}

func (w *WrappingError) Error() string {
   return w.msg
}

func (w *WrappingError) Unwrap() error {
   return w.err
}

type AErr struct{ WrappingError }
type BErr struct{ WrappingError }

...this gives individual error types AErr and BErr without having to 
copy-and-paste everything everytime a new wrapping error type is needed.

Now with generics I understand that I can't do anything about the type AErr 
... boilerplate. However, what about at least making creating new typed 
wrapping errors less of a boilerplate pain?

Naively, I tried...

func New[T ~struct{ WrappingError }](msg string, err error) error {
   e := T{WrappingError{msg: msg, err: err}}
   return &e
}

...but this get's rejected in Go 1.19: * cannot use &e (value of type *T) 
as type error in return statement:    *T does not implement error (type *T 
is pointer to type parameter, not type parameter)*

I would have liked to use it like this:

err := New[AErr]("this is an error", errors.New("foo"))

Any idea how this could be coded differently to somehow achieve the goal of 
reducing boilerplate pain when it comes to typed wrapping errors? Or is 
this a perfect example of attempting to throw Go generics at something 
generics are not supposed to support...?

Example on the "Better Go Playground": 
https://goplay.tools/snippet/NNPL5m5VekG

-- 
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/41217af0-4780-45b5-b913-fd010e34e98dn%40googlegroups.com.

Reply via email to