Skip to content

proposal: change standard library to check for io.EOF using errors.Is #39155

Closed
@tonistiigi

Description

@tonistiigi

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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions