liveBook · Manning

Io.Writer

As explained in Go by Example

io.Writer is a Go interface whose Write method accepts a byte sequence and returns the number of bytes written and an error.

io.Writer is Go’s small interface for sending bytes to an output destination. Its Write method accepts a byte slice and reports how many bytes were written plus any error: Write(p []byte) (n int, err error). Code can depend on this interface rather than a particular destination, so the same output path can write to standard output, files, network connections, or in-memory buffers. section 5.2.3

type Writer interface {
    Write(p []byte) (n int, err error)
}

The complete interface contains one method, making it easy for output-producing code to accept a general destination. section 5.2.3

A Writer may write fewer bytes than it receives. Callers own the byte slice, allowing them to reuse allocated memory and, when needed, split data across repeated Write calls. That design keeps memory management with the caller instead of requiring each Writer implementation to allocate a new buffer for every write. section 5.2.3

Use io.Writer at boundaries where program logic needs to produce output but should not know whether that output goes to global streams or a test double. For a command-line program, an env structure can hold stdout and stderr as io.Writer fields; production wiring supplies os.Stdout and os.Stderr, while tests supply controlled alternatives. section 5.2.1 section 5.2.2

Capture command output in a test

strings.Builder buffers written data and can later return it as a string, so it is useful for asserting output. Store Builder values in a test environment, then pass their addresses as io.Writer values: &tenv.stdout and &tenv.stderr. The pointer matters: *strings.Builder has Write and satisfies io.Writer, while a nonpointer Builder does not. Its useful zero value avoids separate buffer initialization. section 5.4.2 section 5.4.1

Inject only the dependency a function needs. A top-level run function may reasonably receive an environment containing several dependencies, but an argument parser that only emits diagnostics can take stderr io.Writer directly. The parser can then route flag usage and validation messages through flag.FlagSet.SetOutput, keeping its output observable without constructing a larger environment in every test. section 5.3.2

Choose a Writer implementation to match the job:

  • Use *os.File values such as os.Stdout or os.Stderr for real command-line output. section 5.2.3
  • Use *strings.Builder to retain output for assertions after the code runs. section 5.4.2
  • Use io.Discard when output is irrelevant, such as parser tests that intentionally trigger usage messages. section 5.5.2

Writer supports testability by replacing hard-coded global output with an explicit dependency. Tests can verify normal output and error output independently, while the executable keeps its behavior by supplying the real streams. The same decoupling makes functions easier to understand because their required output channel appears in the function signature. section 5.3.2 section 5.6

Implement a focused Writer

A custom type can satisfy io.Writer by implementing Write. One practice implementation counts the bytes it receives and exposes that count; paired with a Reader implementation, it can be used with io.Copy. This illustrates that a Writer can represent a behavior more specialized than a file or buffer. section 7.7

How Go by Example covers it

How deep it goes
Defines Write’s byte-slice contract and explains partial writes, caller-managed memory, and pointer-based Builder satisfaction.
Examples
Uses stdout and stderr injection, strings.Builder output capture, FlagSet.SetOutput, io.Discard, and a byte-counting custom Writer exercise.
What you can do after
Apply it via standard-library Writers to make command-line output configurable and directly testable.
How it connects
Connects dependency injection with strings.Builder, os.File, flag.FlagSet, io.Discard, and io.Reader.

Also explained in

Compare how 2 books explain io.Writer →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Go by Example. The section links point to the parts of the book it draws on.