New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
proposal: errors: replace sentinel errors with typed constants where possible #63602
Comments
Thanks, that is a good idea. But we can't make that change now, as it will break the Go 1 compatibility guarantee. |
I think a better alternative which type errInvalid struct{}
func (errInvalid) Error() string {
return "invalid argument"
}
type errPermission struct{}
func (errPermission) Error() string {
return "permission denied"
}
type errExist struct{}
func (errExist) Error() string {
return "file already exists"
}
type errNotExist struct{}
func (errNotExist) Error() string {
return "file does not exist"
}
type errClosed struct{}
func (errClosed) Error() string {
return "file already closed"
}
var (
ErrInvalid errInvalid
ErrPermission errPermission
ErrExist errExist
ErrNotExist errNotExist
ErrClosed errClosed
) It technically is possible to reassign them, Would be nice to find a less verbose way to express this. type errInvalid errors.Error["invalid argument"]
var ErrInvalid errInvalid A helper like this would allow to easily create individual errors which wrap a parent error for wildcard checking: type Error[Wrapping error, Message const string] struct{}
func (Error[Wrapping, Message]) Error() string {
return Message
}
func (Error[Wrapping, Message]) Unwrap() error {
var zero Wrapping
return zero
} |
One drawback of using constant string errors is, we can easily invent new errors of the same type: package main
type osError string
func (err osError) Error() string {
return string(err)
}
const ErrInvalid = osError("invalid argument")
func main() {
var myError error = ErrInvalid + " 2"
println(myError.Error())
} Maybe, it is a good idea to add a vet rule: find all modifications of global error values (including the operations taking addresses of global error values). |
To add to this, there's already a precedent for var (
a [4]int
b [3]float32
c [8]string
) |
Without getting too off track, has Go considered adding a |
@psnilesh There is https://go.dev/issue/21130. |
Sentinel errors are a common error handling pattern involving comparisons with global variables. The
oserror
package from the standard library has a good example of how these are typically defined:They come with all the usual caveats of global variables, namely that they can be reassigned:
An alternative, backwards-compatible(?) way of defining these using typed constants is possible:
I haven't thought through the potential downsides or long-term implications of this.
The text was updated successfully, but these errors were encountered: