-
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
os: document that IsExist, IsNotExist, IsTimeout, IsPermission should be avoided in favor of errors.Is #41122
Comments
Thank you for raising this issue. You've indicated that it is a proposal. After reading the text of the issue I think your proposal would be clearer if you could call out what you would like to change in the language. It feels like the proposal you are making is to change the documentation to discourage the use of the |
I would actually prefer This issue is a "reopen" of #36150 because I don't understand the argument of @ianlancetaylor for closing it. |
My concern is that if we change the functions in the os package, that will be an unexpected change for existing programs that are using them. There is a comment in the code that says // Note that this function is not errors.Is:
// underlyingError only unwraps the specific error-wrapping types
// that it historically did, not all errors implementing Unwrap(). CC @neild who added this comment in https://golang.org/cl/163058. @neild Is there a known problem with changing Either way, I've said all along that we should change the docs. |
#421) * Include file path in errors from PartialDriver.ReadUp() and ReadDown() * Use errors.Is(...) instead of os.Is...() in migrate.go: golang/go#41122
We spent a long time on this in the error designs. It is an understandable caution about backwards compatibility without a specific, known problem. It is sure to break existing code, and error-handling is not always well tested (it's just hard to test). Now that all supported versions of Go provide errors.Is, we should update the doc comments on these functions to suggest using errors.Is instead. |
A specific, known problem is that this violation of the principle of least astonishment causes people to misuse the functions in real code, for example, golang-migrate/migrate@04fb8d6 |
Let's document this for Go 1.16 at least. This just bit me too. I was testing an error from |
…s errors. os.IsNotExist doesn't unwrap errors. errors.Is does. The ioutil.ReadFile ones happened to be fine but I changed them so we're consistent with the rule: if the error comes from os, you can use os.IsNotExist, but from any other package, use errors.Is. (errors.Is always would also work, but not worth updating all the code) The motivation here was that we were logging about failure to migrate legacy relay node prefs file on startup, even though the code tried to avoid that. See golang/go#41122
Change https://golang.org/cl/268897 mentions this issue: |
This commit replaces the error checks using the `os.Is{...}` functions - e.g. `os.IsExist(err)` - with the more generic `errors.Is(err, ...)`. In general, the `os.Is{...}` functions should not be used. See: golang/go#41122
This commit replaces the error checks using the `os.Is{...}` functions - e.g. `os.IsExist(err)` - with the more generic `errors.Is(err, ...)`. In general, the `os.Is{...}` functions should not be used. See: golang/go#41122
I thought all these functions to be exact semantic equivalent of
errors.Is(err, os.ErrExist)
,errors.Is(err, os.ErrnotExist)
,and
errors.Is(err, os.ErrPermission)
, respectively. I was highly surprised to find they don't.@ianlancetaylor suggested that "Maybe we should simply change "the error" to "an error returned from this package.", regarding the doc for
os.IsNotExist()
:I don't think it's enough because it still requires a great deal of attention to notice the semantic difference with
errors.Is(err, os.ErrnotExist)
by just reading the suggested edited docNot to mention that when a developer looks at the signature of this function, it appears very simple and looks like it has an obvious meaning, so I suspect most developers don't even read the doc for this function. For example, I think I didn't, before I stumbled upon the semantic mismatch.
To the attention of Golang maintainers, please consider that people who started using Golang after
errors.Is()
was introduced don't have the hindsight of remembering thatos.Is...
functions existed beforeerrors.Is()
and thus should probably mean something special or "historic".The text was updated successfully, but these errors were encountered: