liveBook · Manning

Io.Reader

As explained in 100 Go Mistakes and How to Avoid Them

io.Reader is a Go interface for reading bytes from a data source.

A common mistake is designing a function around filenames or *os.File values when it only needs to consume bytes. io.Reader defines a smaller boundary: a value supplies Read(p []byte) (n int, err error), filling the caller-provided slice. Go types satisfy this interface implicitly, without an implements declaration. section 2.5.1

Use the abstraction when the operation should remain independent of its source:

  • Accept io.Reader rather than a filename when callers may provide files, strings, bytes, or other data sources. section 2.5.1
  • Pair io.Reader with io.Writer to copy data without coupling the operation to a particular source or destination type. section 2.5.1
  • Test reader-consuming code with strings.Reader instead of managing files; use bytes.Buffer as a convenient destination when the operation also accepts io.Writer. section 2.5.1 section 6.7

A reader-based copy test

Define copySourceToDest(source io.Reader, dest io.Writer) error. In a test, create source := strings.NewReader("foo") and dest := bytes.NewBuffer(make([]byte, 0)); call the function, then compare dest.String() with the input. The test checks the behavior without opening a file. section 2.5.1

The method signature also reflects an allocation-conscious API choice. The caller supplies the byte slice, while Read reports the number of bytes read and an error; returning a newly allocated slice would automatically make that slice escape to the heap. section 12.6.1

type Reader interface {
    Read(p []byte) (n int, err error)
}

The compact interface declaration makes the contract explicit: callers provide storage, and implementations report progress and failure. section 2.5.1

How 100 Go Mistakes and How to Avoid Them covers it

How deep it goes
Defines the single Read contract, demonstrates generic use and testing, and connects the caller-provided slice to escape analysis.
Examples
Uses copySourceToDest with strings.Reader and bytes.Buffer, plus contrasting Read signatures for allocation behavior.
What it assumes
Assumes familiarity with Go interfaces, methods, slices, errors, and basic unit testing while explaining implicit interface satisfaction.
What you can do after
Build reusable and testable byte-consuming functions by accepting io.Reader instead of concrete filenames or file types.
How it connects
Connects interfaces, io.Writer, files, strings.Reader, bytes.Buffer, unit testing, and escape analysis.

Also explained in

Compare how 3 books explain io.Reader →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of 100 Go Mistakes and How to Avoid Them. The section links point to the parts of the book it draws on.