Skip to content

io: make MultiReader documentation more explicit #7216

@gopherbot

Description

@gopherbot

by ryguillian:

I'm running Go 1.2.

My issues are about io.MultiReader: I went to go use MultiReader and its behavior
confused me.

MultiReader's documentation sez: 

“MultiReader returns a Reader that's the logical concatenation of the provided input
readers. They're read sequentially. Once all inputs are drained, Read will return EOF.”

This documentation is pretty bad. It only says what happens once “all inputs are
drained”—whatever the hell that means. 

I wish this were just a bug report about documentation, but I'm sad to say I think
MultiReader's behavior is pretty dumb.

Like, uh, is MultiReader.Read supposed to stop after the first Reader returns EOF?
Because that's what it does.

In other words, if I run `cat file1 file2 file3` I get the concatenation of file1,
file2, and file3. Even if file2 is empty! I only use this example because Go is replete
with analogies to Unix commandlineisms (io.MultiWriter mentions 'tee(1)' explicitly).
And in case differs drastically from the expected behavior. Although in a talk I saw
online Rob Pike said something about breaking analogies, so I guess it's OK. Right?

Go is obviously very opinionated software, and that's good. But if you want the user to
use io.ReadAtLeast to get the expected behavior then document it. Although I'd argue
that using io.ReadAtLeast to invoke a continuation (think about it) is a little too
subtle for me.

I'd argue for changing the behavior of this, though. It's weird because you're providing
an abstraction over Readers and then still preserving reader boundaries. I guess this
all has to work with network code where things can get unpredictable. If that's what led
to this wacky design, then maybe offer a non-network-oriented MultiReader. This seems
more like a 'ReaderPool' or something.

It just seems hard to imagine a case where you'd have intermittently available resources
somewhere and want to still read them sequentially. I suppose I could contrive an
example, but this can't be the #1 use case. I can imagine a lot more situations where
you'd want to do something like a queue and use MultiReader to read from the queue if
it's not empty and then read from an underlying Reader otherwise. "And then"
is implicit when you use a word like "logical concatenation".

So yeah, I'd call for the redesign of
io.MultiReader.readLessThanSliceLengthOrIfEOFReturnNilCallAgainIfYouWantMore.

Thanks,

Ryan

P.S. The only code in the Go 'pkg' directory that uses MultiReader is
'io/multireader_test.go'.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions