Skip to content

proposal: io: add ReadSome #48182

Closed
Closed
@bradfitz

Description

@bradfitz

The io.Reader.Read method is notoriously tricky, with lots of docs: https://pkg.go.dev/io#Reader

In particular, it's common for people new to Go to write:

var buf [N]byte
_, err := r.Read(buf[:])

... and think they're reading N bytes. Especially when it almost always works. The testing/iotest package is easy to miss (and easier to just not use, even when you're aware of it).

I regularly correct that pattern in code reviews when I see others make that mistake, and despite writing Go for over 11 years, I also made that mistake the other day, causing problems today.

The io package has these helpers that, in addition to doing as documented, also declare the author's intent:

func ReadAll(r Reader) ([]byte, error)
func ReadAtLeast(r Reader, buf []byte, min int) (n int, err error)
func ReadFull(r Reader, buf []byte) (n int, err error)

When the author writes the snippet at top, though, it's hard to know intent. Sometimes it's actually legit to read fewer:

var buf [1500]byte
if n, err := conn.Read(buf[:]); err != nil {
  panic(err)
}
processIncomingUDPPacket(buf[:n])

It'd almost be nice to have a new "helper" in the io package like:

package io

// ReadSome returns r.Read(buf).
//
// It does nothing extra besides declare your intent that you're
// cool with n being < len(buf).
func ReadSome(r io.Reader, buf []byte) (n int, err error) { return r.Read(buf) }

Then all raw io.Reader.Read calls could be replaced with io.ReadFull, io.ReadSome etc, and a raw calls would then stand out as shady, warranting further inspection or annotation.

People who wanted to be really strict could make their static analysis tool(s) of choice even forbid raw Read calls.

/cc @danderson @dsnet

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions