• English
  • Example: io.ReadFull

    io.ReadFull reads from an io.Reader until the buffer is completely filled or an error occurs.

    A single call to Reader.Read may return fewer bytes than requested, even when more data is available. io.ReadFull keeps reading until len(buf) bytes have been read or the input ends.

    If it returns err == nil, the buffer is guaranteed to be completely filled.

    Quick Example

    Read exactly 5 bytes:

    package main
    
    import (
    	"fmt"
    	"io"
    	"strings"
    )
    
    func main() {
    	src := strings.NewReader("Hello, io.ReadFull from gobase.net.")
    
    	buf := make([]byte, 5)
    	if _, err := io.ReadFull(src, buf); err != nil {
    		fmt.Println("read failed:", err)
    		return
    	}
    
    	fmt.Printf("%s\n", buf)
    }

    Output:

    Hello

    The key difference from Reader.Read is the completion guarantee:

    n, err := r.Read(buf)

    may return n < len(buf) with err == nil.

    With:

    n, err := io.ReadFull(r, buf)

    err == nil means n == len(buf).

    Common Use

    Fixed-Length Protocol Headers

    Binary protocols often begin with a fixed-size header.

    For example:

    +----------------+----------------+
    | Magic (4 bytes)| Length (4 bytes)|
    +----------------+----------------+
    |            Payload             |
    +--------------------------------+

    Read the complete header before parsing its fields:

    func readHeader(r io.Reader) (uint32, error) {
    	header := make([]byte, 8)
    
    	if _, err := io.ReadFull(r, header); err != nil {
    		return 0, err
    	}
    
    	return binary.BigEndian.Uint32(header[4:]), nil
    }

    This matters especially for network streams such as TCP, where one Read does not correspond to one message or one Write.

    The same pattern applies to fixed-size records, file headers, binary message fields, and framed protocols.

    Common Mistakes

    1. Assuming Read fills the buffer

    This is not guaranteed:

    n, err := r.Read(buf)

    n may be smaller than len(buf) even when no error occurred.

    Use io.ReadFull when the operation requires an exact number of bytes.

    2. Treating io.EOF and io.ErrUnexpectedEOF as the same

    io.ReadFull distinguishes between a clean end before reading anything and an incomplete read:

    ErrorMeaning
    nilThe buffer was completely filled.
    io.EOFNo bytes were read before the reader reached EOF.
    io.ErrUnexpectedEOFSome bytes were read, but EOF occurred before the buffer was filled.

    For a fixed-length protocol field, io.ErrUnexpectedEOF usually means the message is incomplete or truncated.

    3. Ignoring the byte count on errors

    io.ReadFull returns the number of bytes successfully read even when it returns an error:

    n, err := io.ReadFull(r, buf)

    If err != nil, n tells you how much of the requested data was actually received.

    4. Using io.ReadFull when partial reads are acceptable

    io.ReadFull is for exact-size reads.

    If the caller can process whatever data is currently available, a normal Reader.Read may be more appropriate.

    Rule of Thumb

    Use io.ReadFull when success requires exactly len(buf) bytes.