-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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
all: updating existing errors to work with the Go 1.13 error values #30322
Comments
Thanks for writing up this list! (And sorry for taking so long to respond.) My current plan is to add Taking each point in turn, my personal opinion:
Existing
Wrapper error types should have
In general, yes, although there might be exceptions where location information adds no useful context and can be omitted.
In general, yes.
Types with an
Not in any cases that I've seen yet.
I'm ambivalent on whether we should mark the older approach as deprecated or not. |
I wrote a program to analyze the 1.12 release's use of errors. It inspects each .go file, regardless of build tags, skipping testdata and cmd directories. It collects custom error types, use of Errorf that may wrap an error, direct calls to an Error method. The report and program are in this gist: https://gist.github.com/jimmyfrasche/51b83022f83ccbe240092dcd884605cd While I plan to, I have yet to explore the larger packages: crypto/{tls, x509}, encoding/{json, xml}, or anything under go, internal/x, net, os, or syscall I went through everything else in the stdlib, though. I'm sure a lot of this on the radar and I'm even surer that I've missed things as this was a quick and superficial exploration, but another pair of eyes never hurts. Here's what I've found so far: Types with an Err field that could use an Unwrap method:
Types with Temporary()/Timeout() methods:
For errors that get wrapped without a way to get to the underlying error (mostly via fmt.Printf, but there is one exception below), most seem benign but there are a number that wrap IO errors. Arguably that's correct, but I note them regardless. In image/png an IO error is wrapped in a FormatError but that type's represented as a string so I suspect there's little to be done about that. Packages that wrap IO errors by calls to fmt.Errorf:
There's one other case where I found errors wrapped with fmt.Errorf: database/sql conversions. These wrap errors provided by the database driver. It might be a good idea to change these to %w. For example, postgres has a rich type system and data type conversion errors can contain user defined messages so being able to get to a driver defined error type could be a win. |
Change https://golang.org/cl/163058 mentions this issue: |
As proposed in Issue #29934, update errors produced by the os package to work with errors.Is sentinel tests. For example, errors.Is(err, os.ErrPermission) is equivalent to os.IsPermission(err) with added unwrapping support. Move the definition for os.ErrPermission and others into the syscall package. Add an Is method to syscall.Errno and others. Add an Unwrap method to os.PathError and others. Updates #30322 Updates #29934 Change-Id: I95727d26c18a5354c720de316dff0bffc04dd926 Reviewed-on: https://go-review.googlesource.com/c/go/+/163058 Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
Change https://golang.org/cl/170037 mentions this issue: |
Add Unwrap methods to types which wrap an underlying error: "encodinc/csv".ParseError "encoding/json".MarshalerError "net/http".transportReadFromServerError "net".OpError "net".DNSConfigError "net/url".Error "os/exec".Error "signal/internal/pty".PtyError "text/template".ExecError Add os.ErrTemporary. A case could be made for putting this error value in package net, since no exported error types in package os include a Temporary method. However, syscall errors returned from the os package do include this method. Add Is methods to error types with a Timeout or Temporary method, making errors.Is(err, os.Err{Timeout,Temporary}) equivalent to testing the corresponding method: "context".DeadlineExceeded "internal/poll".TimeoutError "net".adrinfoErrno "net".OpError "net".DNSError "net/http".httpError "net/http".tlsHandshakeTimeoutError "net/pipe".timeoutError "net/url".Error Updates #30322 Updates #29934 Change-Id: I409fb20c072ea39116ebfb8c7534d493483870dc Reviewed-on: https://go-review.googlesource.com/c/go/+/170037 Run-TryBot: Damien Neil <dneil@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
Change https://golang.org/cl/194563 mentions this issue: |
Change https://golang.org/cl/194599 mentions this issue: |
Change https://golang.org/cl/194817 mentions this issue: |
Jay suggested this in CL 189780, and it seems semantically correct. As far as I can tell this has no impact one way or the other right now, but might prevent confusion (or at least give us more experience with error handling!) in future changes. Updates #30748 Updates #28459 Updates #30322 Change-Id: I5d7e9a08ea141628ed6a8fd03c62d0d3c2edf2bb Reviewed-on: https://go-review.googlesource.com/c/go/+/194817 Run-TryBot: Bryan C. Mills <bcmills@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Jay Conrod <jayconrod@google.com>
Updates #30322 This change adds the Unwrap method to NumError. NumError is the only custom error type of the strconv that has a nested exported error. Change-Id: I8774886348880365a83f72a1d106276def27dffe GitHub-Last-Rev: 712f3df GitHub-Pull-Request: #34213 Reviewed-on: https://go-review.googlesource.com/c/go/+/194563 Run-TryBot: Bryan C. Mills <bcmills@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Bryan C. Mills <bcmills@google.com>
|
type CertificateInvalidError struct {
Cert *Certificate
Reason InvalidReason
Detail string
}
if errors.Is(err, x509.Expired) { ... } as an alternative to: if e, ok := err.(*x509.CertificateInvalidError); ok && e.Reason == x509.Expired { ... } That actually looks rather nice. |
Change https://golang.org/cl/217132 mentions this issue: |
Updates #30322 Updates #36878 Change-Id: I8b33eb6a8fb7c0ecf365940a1c3ae88dc807ebcd Reviewed-on: https://go-review.googlesource.com/c/go/+/217132 Reviewed-by: Bryan C. Mills <bcmills@google.com>
Change https://golang.org/cl/262343 mentions this issue: |
This change modifies Go to add the Unwrap method to SystemRootsError Updates #30322 Change-Id: Ibe63d1d0bc832fc0607f09053908d55275a6f350 GitHub-Last-Rev: 9a95bc6 GitHub-Pull-Request: #41981 Reviewed-on: https://go-review.googlesource.com/c/go/+/262343 Reviewed-by: Damien Neil <dneil@google.com> Reviewed-by: Filippo Valsorda <filippo@golang.org> Trust: Damien Neil <dneil@google.com> Run-TryBot: Filippo Valsorda <filippo@golang.org> TryBot-Result: Go Bot <gobot@golang.org>
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
Unwrap
method?FormatError
method?Is
method?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 vsos.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 generalerrors.Is(err, os.ErrTimeout)
instead ofos.IsTimeout(err)
.The predicate methods defined in
net.Error
offer a similar approach. In the case ofIsTimeout
, overlapping. To test a general error for this method you can writeThis is slightly more verbose than the
Is
construct.Adding an
Is
method tonet.Error
s that respond toErrTimeout
and anErrTemporary
could make it more likeos
. Adding predicate methods to theos
errors could make them more likenet
. 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 errorB
and either may be temporary but onlyB
is. TheAs
construct setstimeout
toA
whose method returns false (unless it inspects the chain on its own) but theIs
construct returns true. If the intent is to override the temporary-ness ofB
anIs
method onA
that returns false forErrTemporary
is easy enough. It seems both more flexible and concise.The text was updated successfully, but these errors were encountered: