Skip to content
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

proposal: Go 2: io: require io.Reader to return either n > 0 or an error #27531

Open
crawshaw opened this issue Sep 6, 2018 · 5 comments

Comments

@crawshaw
Copy link
Contributor

commented Sep 6, 2018

Today the Read method of an io.Reader is allowed to return 0, nil. It is uncommon and discouraged:

Implementations of Read are discouraged from returning a zero byte
count with a nil error, except when len(p) == 0. Callers should treat a
return of 0 and nil as indicating that nothing happened; in particular
it does not indicate EOF.

It is so uncommon that it is hard to remember to deal with this case when using an io.Reader. All correct calls to Read need to be wrapped in a loop that tries multiple times, and after some ill-defined cutoff, report an error like io.ErrNoProgress. Consider the correct example of reading from bufio.Reader:

// Read new data: try a limited number of times.
for i := maxConsecutiveEmptyReads; i > 0; i-- {
	n, err := b.rd.Read(b.buf[b.w:])
	if n < 0 {
		panic(errNegativeRead)
	}
	b.w += n
	if err != nil {
		b.err = err
		return
	}
	if n > 0 {
		return
	}
}
b.err = io.ErrNoProgress

For Go 2 I propose we change the contract of io.Reader so implementations are required to return either n > 0 or a non-nil error.

@crawshaw crawshaw added the Go2 label Sep 6, 2018

@gopherbot gopherbot added this to the Proposal milestone Sep 6, 2018

@gopherbot gopherbot added the Proposal label Sep 6, 2018

@bcmills

This comment has been minimized.

Copy link
Member

commented Sep 6, 2018

I think if we wanted to do that we would also need to change the name of the method.

We want Go 1 and Go 2 APIs to be able to coexist in the same program, and per https://research.swtch.com/vgo-import, that requires that “when you change a function’s behavior, you also change its name.”

@ianlancetaylor ianlancetaylor changed the title proposal: io: require io.Reader to return either n > 0 or an error proposal: Go 2: io: require io.Reader to return either n > 0 or an error Sep 6, 2018

@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

commented Sep 6, 2018

It would be useful to know whether there are any existing implementations of io.Reader that can return zero with no error. If there are any, why do they exist?

See #5309 and #5310. In particular #5309 suggests that (*tls.Conn).Read() could return (0, nil). Is that still the case?

@bcmills

This comment has been minimized.

Copy link
Member

commented Sep 6, 2018

It would be useful to know whether there are any existing implementations of io.Reader that can return zero with no error. If there are any, why do they exist?

I think the net.Conns returned by net.Pipe can. I believe the reason is so that Write can unblock a pending Read without closing the pipe, but I'm not really sure.

(I didn't find a compelling reason the last time I checked: #24205 (comment).)

@dsnet

This comment has been minimized.

Copy link
Member

commented Sep 6, 2018

Though undocumented, the flate.Reader can return (0, nil) when it encounters successive Z_SYNC_FLUSH markers. There are tests to preserve this behavior and some network protocols depend on this.

EDIT: I just checked. flate.Reader actually only returns on SYNC_FLUSH if there at least some number of bytes read (example). That said, I got an email recently complaining that the reader did not return on all SYNC_FLUSH, which would imply that it may return (0, nil).

@splace

This comment has been minimized.

Copy link

commented Jun 28, 2019

surely the contract, put as a conversation, is...

reader.Read == 'i want some bytes in this buffer, let me know how many you have put in it and if there is a problem that effects me repeating this action'.

the reader Reads without knowledge of how many are available, isn't this isolation a fundamental point of a reader.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
6 participants
You can’t perform that action at this time.