Using generics to handle error types

I wanted to hear the community’s thoughts on using generics to do things like testing an error by its type rather than its value. The following snippet is part of a code that I’ve been writing to get a feel of how generics works in Go as of 1.18:

package handy

import "errors"

// As is an inline form of errors.As.
func As[Error error](err error) (Error, bool) {
	var as Error
	ok := errors.As(err, &as)
	return as, ok
}

// IsType reports whether or not the type of any error in err's chain matches
// the Error type.
func IsType[Error error](err error) bool {
	_, ok := As[Error](err)
	return ok
}

To be completely honest this feels very gimmicky and un-Go like to me. It is legal Go code but it feels like an abuse of generics. However at the same time, it is very useful in situations where the type of the error matters rather than the value (eg. checking for ent.ConstraintError type to catch and handle constraint errors). While ent.ConstraintError can be caught using ent.IsConstraintError(err), in my case I wanted to separate the ORM layer from the rest of my application so I wrapped the error in a custom type, but writing a myapp.IsXxxError was cumbersome. My instinct pre-generics would have been “just write the myapp.IsXxxError function”, but with generics I started to wander around to see if at least I can do it.

I’ve also come up with some hacks like creating value-initialized pointers but I feel the same about this too:

package handy

// New returns a pointer initialized with the given value.
func New[T any](v T) *T {
	return &v
}

It sure is handy to use but I’m having a sort of identity crisis where it feels like the code I’m writing is deviating away from the design principles of Go. I’d love to hear your feedback.

1 Like

Can’t you make decisions on the dynamic type easier with type assertions or type switches?

That’s true if error types are returned directly but if they are wrapped it can’t be done (to my knowledge anyway: hence errors.Is and errors.As as noted in the errors package overview errors package - errors - pkg.go.dev).