liveBook · Manning

Io.Copy

As explained in Go by Example

io.Copy is a Go standard-library function that copies bytes from an io.Reader to an io.Writer and returns the number of bytes copied and any error.

io.Copy transfers bytes from an io.Reader to an io.Writer and returns the number of bytes written plus any transfer error. It reuses a 32 KB buffer, so a response can be processed without loading its complete contents into memory. section 7.3.4

Count an HTTP response without storing it

numberOfBytesDownloaded, err := io.Copy(io.Discard, response.Body) io.Discard receives and drops the downloaded bytes, while io.Copy returns the total transferred. This pattern is useful when only the response size matters. Close response.Body after processing it so the HTTP connection can be reused. section 7.3.4 section 7.3.5

Use io.Copy when:

  • Streaming between files, network connections, response bodies, or in-memory buffers through the io.Reader and io.Writer interfaces. section 7.3.4
  • Large input makes io.ReadAll unnecessarily memory-intensive; Copy keeps its transfer buffer bounded. section 7.3.4
  • A custom buffer size is needed; use io.CopyBuffer to trade buffer memory against read and write operation overhead. section 7.3.4
  • The source reaches the end normally; io.Copy consumes io.EOF and returns nil rather than reporting EOF as an error. section 7.3.5
func Copy(
    dst io.Writer,  #1
    src io.Reader,  #2
) (written int64, err error)  #3

The signature makes the direction explicit: dst is the io.Writer, src is the io.Reader, and the result reports bytes written and an error. section 7.3.4

Listing 7.4 Processing a request and response (hit/hit.go)
package hit

import (
    . . .
    "io"
)
. . .
func Send(client *http.Client, req *http.Request) Result {
    started := time.Now()
    var (
        bytes int64
        code  int
    )
    resp, err := client.Do(req)  #1
    if err == nil { // no error  #2
        defer resp.Body.Close()  #3
        code = resp.StatusCode
        bytes, err = io.Copy(  #4
            io.Discard,  #5
            resp.Body,  #6
        )
    }
    return Result{
        Duration: time.Since(started),  #7
        Bytes:    bytes,
        Status:   code,
        Error:    err,
    }
}

A complete HTTP helper calls io.Copy with io.Discard and resp.Body, records the byte count, handles the request error, and defers body closure. section 7.3.5

How Go by Example covers it

How deep it goes
Explains the Reader-to-Writer contract, 32 KB buffering, return values, EOF handling, and CopyBuffer trade-offs.
Examples
Uses discarded HTTP downloads, a complete Send helper, configurable buffers, and exercises with custom Reader and Writer implementations.
What it assumes
Assumes familiarity with HTTP clients and response bodies while reinforcing io.Reader, io.Writer, error handling, and resource closure.
What you can do after
Apply io.Copy to stream HTTP bodies and other I/O sources while measuring transferred bytes and controlling memory use.
How it connects
Connects io.Reader, io.Writer, io.Discard, io.ReadAll, io.CopyBuffer, io.EOF, and HTTP response-body management.

Also explained in

Compare how 2 books explain io.Copy →

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.