io defines the Reader, Writer, and Closer interfaces every other I/O package builds on, plus a set of functions for copying, combining, and wrapping them without caring what's on the other end.
Examples
Copy reads src to EOF and writes everything to dst, returning the byte count it moved.
src := strings.NewReader("hello, io")
var dst bytes.Buffer
n, err := io.Copy(&dst, src)
fmt.Println(n, err)
fmt.Println(dst.String())9
hello, io TeeReader lets a single pass over src both consume the data and feed a second writer, here a hash, without buffering the whole thing twice.
src := strings.NewReader("hello, io")
h := sha256.New()
tee := io.TeeReader(src, h)
data, _ := io.ReadAll(tee)
fmt.Println(string(data))
fmt.Printf("%x\n", h.Sum(nil)[:6])hello, io
abfe060fc10cMultiWriter fans a single write out to several destinations at once. MultiReader does the opposite: it stitches several readers into one, exhausting each in order.
var a, b bytes.Buffer
w := io.MultiWriter(&a, &b)
io.WriteString(w, "logged twice")
fmt.Println(a.String())
fmt.Println(b.String())
r := io.MultiReader(strings.NewReader("foo-"), strings.NewReader("bar"))
data, _ := io.ReadAll(r)
fmt.Println(string(data))logged twice
logged twice
foo-barA SectionReader carves out a fixed window of an underlying ReaderAt. Read advances through that window; ReadAt jumps to any offset inside it without disturbing Read's own position.
base := strings.NewReader("0123456789abcdefghij")
sec := io.NewSectionReader(base, 5, 5)
fmt.Println(sec.Size())
buf := make([]byte, 5)
n, err := sec.Read(buf)
fmt.Println(n, err, string(buf[:n]))
b2 := make([]byte, 3)
n2, err2 := sec.ReadAt(b2, 1)
fmt.Println(n2, err2, string(b2[:n2]))5
5 56789
3 678 Pipe connects a Reader end to a Writer end with no buffer between them. The write has to happen on its own goroutine, since a Write blocks until a matching Read drains it.
r, w := io.Pipe()
go func() {
w.Write([]byte("streamed"))
w.Close()
}()
data, _ := io.ReadAll(r)
fmt.Println(string(data))streamed| Function | Description |
|---|---|
EOF | Sentinel error returned by Read when no more input is available. |
ErrUnexpectedEOF | Returned when EOF arrives mid-structure, after some but not all of the expected data was read. |
ErrShortWrite | Returned when a write accepted fewer bytes than it was given, with no other explanation. |
ErrShortBuffer | Returned when a read needs a larger buffer than the one it was given. |
ErrClosedPipe | Returned by Pipe operations performed after the pipe has already been closed. |
ErrNoProgress | Returned by callers of ReadAtLeast-style loops after many consecutive reads return no data and no error. |
SeekStart | Seek whence value: offset is relative to the start of the file. |
SeekCurrent | Seek whence value: offset is relative to the current offset. |
SeekEnd | Seek whence value: offset is relative to the end. |
Discard | A Writer that discards everything written to it, like /dev/null. |
Reader | Wraps the basic Read(p []byte) (n int, err error) method. |
Writer | Wraps the basic Write(p []byte) (n int, err error) method. |
Closer | Wraps the basic Close() error method. |
Seeker | Wraps the basic Seek(offset int64, whence int) (int64, error) method. |
ReaderAt | ReadAt(p []byte, off int64) (n int, err error): reads at a fixed offset without moving any implicit cursor. |
WriterAt | WriteAt(p []byte, off int64) (n int, err error): writes at a fixed offset without moving any implicit cursor. |
ReaderFrom | ReadFrom(r Reader) (n int64, err error): pulls data from r until EOF. |
WriterTo | WriteTo(w Writer) (n int64, err error): pushes all of a value's data to w. |
ByteReader | ReadByte() (byte, error): reads a single byte. |
ByteScanner | ByteReader plus UnreadByte() error, putting the last byte read back. |
ByteWriter | WriteByte(c byte) error: writes a single byte. |
RuneReader | ReadRune() (r rune, size int, err error): reads one UTF-8-decoded rune. |
RuneScanner | RuneReader plus UnreadRune() error, putting the last rune read back. |
StringWriter | WriteString(s string) (n int, err error): writes a string without a []byte conversion. |
ReadWriter | Combines Reader and Writer. |
ReadCloser | Combines Reader and Closer. |
WriteCloser | Combines Writer and Closer. |
ReadWriteCloser | Combines Reader, Writer, and Closer. |
ReadSeeker | Combines Reader and Seeker. |
WriteSeeker | Combines Writer and Seeker. |
ReadWriteSeeker | Combines Reader, Writer, and Seeker. |
ReadSeekCloser | Combines Reader, Seeker, and Closer. |
Copy(dst, src) (written int64, err error) io.Copy(&buf, r) // 9, nil | Copies from src to dst until EOF on src or an error. |
| |
CopyBuffer(dst, src, buf) (written int64, err error) | Like Copy, but uses the caller-supplied buffer instead of allocating one. |
| |
CopyN(dst, src, n) (written int64, err error) io.CopyN(&buf, r, 5) // 5, nil | Copies exactly n bytes from src to dst, or returns an error trying. |
ReadAll(r Reader) ([]byte, error) io.ReadAll(r) // []byte("hello"), nil | Reads from r until EOF and returns everything read; EOF itself is not reported as an error. |
ReadAtLeast(r, buf, min) (n int, err error) | Reads from r into buf until at least min bytes have arrived. |
| |
ReadFull(r Reader, buf []byte) (n int, err error) | Reads from r until buf is completely full. |
| |
WriteString(w Writer, s string) (n int, err error) io.WriteString(w, "hi") // 2, nil | Writes s to w, calling w's own WriteString method directly when w implements StringWriter. |
LimitReader(r Reader, n int64) Reader io.LimitReader(r, 3) | Returns a Reader that reads from r but reports EOF after n bytes. |
LimitedReader | The struct LimitReader returns: exported fields R Reader and N int64, the remaining byte budget. |
MultiReader(readers ...Reader) Reader io.MultiReader(r1, r2) // reads r1 fully, then r2 | Concatenates readers into one logical Reader, read in sequence. |
MultiWriter(writers ...Writer) Writer io.MultiWriter(w1, w2) | Duplicates every write across all of the given writers. |
TeeReader(r Reader, w Writer) Reader io.TeeReader(r, hasher) | Returns a Reader that also writes to w everything read from r, as it's read. |
NopCloser(r Reader) ReadCloser | Wraps r with a no-op Close method, for call sites that require a ReadCloser but need no real cleanup. |
OffsetWriter | A WriterAt that adds a fixed base offset to every WriteAt call. |
NewOffsetWriter(w WriterAt, off int64) *OffsetWriter | Constructs an OffsetWriter around w, starting at off. |
SectionReader | A ReadSeeker and ReaderAt limited to a fixed section of an underlying ReaderAt. |
NewSectionReader(r ReaderAt, off, n int64) *SectionReader io.NewSectionReader(r, 5, 5) | Constructs a SectionReader over n bytes of r starting at off. |
(*SectionReader) Read(p []byte) (n int, err error) | Reads within the section, advancing the section's own internal offset. |
(*SectionReader) ReadAt(p []byte, off int64) (n int, err error) | Reads at off relative to the section's start, ignoring and not advancing the internal offset. |
(*SectionReader) Seek(offset int64, whence int) (int64, error) | Moves the section's internal offset, bounded by the section's own start and length. |
(*SectionReader) Size() int64 | Returns the section's fixed length, exactly the n given to NewSectionReader. |
Pipe() (*PipeReader, *PipeWriter) | Creates an in-memory, synchronous pipe connecting a Reader end and a Writer end. |
A pipe has no internal buffer: a | |
PipeReader | The read half of a Pipe; each Read blocks until a matching Write supplies data. |
PipeWriter | The write half of a Pipe; each Write blocks until a matching Read consumes it. |