Description
Go1.13 introduced errors.Is/As/Unwrap
for adding typed information to errors. With this change, errors turn into chains of values instead of a plain string. I think this is a significant improvement, but one of the issues stopping us from getting the full benefit from this is that the error checks inside stdlib still use the old ==
equality check instead of errors.Is
.
This means that whenever we wrap errors with extra type information, we need to make sure these errors are not returned by any interface that might be passed to stdlib.
The most common case for this is io.Reader
that should return io.EOF
when there is no more data. With a quick search, I found that there are over 200 places in stdlib today where EOF
is checked with ==
condition. For a typical example, io.Copy
uses a check like this to determine if reader error also becomes a copy error. If we would change all these places to use errors.Is(err, io.EOF)
instead, custom implementations of io.Reader
could return much more useful errors.
For example, http.RoundTripper
implementation could associate the request/response body with the information about the request, so that when an error happens later, it contains information about what specific request produced the data that ended up failing. Currently, most of the time, we would just get an unexpected EOF
or broken pipe
in this case.
I'm not suggesting any of the current io.EOF
errors returned from stdlib (eg. os.File) should be wrapped. That would not be backward compatible. But just changing the internal equality checks and documenting it should be harmless.
Initially, 3rd party libraries will still likely check io.EOF
directly, but over time they will get updated as well. Before stdlib makes the change and provides an official recommendation, they don't have any incentive to do that.