-
Notifications
You must be signed in to change notification settings - Fork 18.3k
Description
This issue is for discussing how to update errors in the standard library and golang.org/x packages to work with the Go 2 error values changes proposed in #29934.
That issue is for discussing the proposal itself. This is for discussing how best to update existing error types to make the most use of the new additions to the errors package, assuming that it is accepted.
All calls to errors.New
will be updated automatically.
All calls to fmt.Errorf
that do not wrap errors will be updated automatically. Those that wrap errors will not be.
No custom types, outside of the errors package itself, will be updated automatically.
How will the errors that would require manual updating be updated?
For fmt.Errorf
the only question is whether to turn a %s
/%v
to a %w
.
For custom types, the questions are
- should they have an
Unwrap
method? - should they collect stack frames?
- should they have a
FormatError
method? - Do any require an
Is
method? - An
As
Method?
If one of the above obviates an older approach (like an Err error
field on a struct) should the older approach be marked deprecated?
Even with a general policy, there will likely be exceptions.
net.Error
's extra methods vs os.IsTimeout
and co. is a particular wrinkle.
The os.IsX
predicates test the underlying error of a finite set of error types for certain (platform specific) error values. This does not work with arbitrarily wrapped errors. @neild's https://golang.org/cl/163058 contains a proof-of-concept for changing it so that one can write the more general errors.Is(err, os.ErrTimeout)
instead of os.IsTimeout(err)
.
The predicate methods defined in net.Error
offer a similar approach. In the case of IsTimeout
, overlapping. To test a general error for this method you can write
var timeout interface { IsTimeout() bool }
if errors.As(err, &timeout) && timeout.IsTimeout() { //etc.
This is slightly more verbose than the Is
construct.
Adding an Is
method to net.Error
s that respond to ErrTimeout
and an ErrTemporary
could make it more like os
. Adding predicate methods to the os
errors could make them more like net
. Ideally they would be the same because if they're wrapped in further errors the code inspecting them may not know which package the original comes from and would have to handle both.
The approaches are not equivalent when there are multiple errors in the chain that can have the same property. Say error A
wraps error B
and either may be temporary but only B
is. The As
construct sets timeout
to A
whose method returns false (unless it inspects the chain on its own) but the Is
construct returns true. If the intent is to override the temporary-ness of B
an Is
method on A
that returns false for ErrTemporary
is easy enough. It seems both more flexible and concise.