HowtoGo
Standard Library

bufio

bufio wraps a Reader or Writer to cut down on syscalls, and adds line/word/rune scanning.

The smallest useful thing bufio does is read one line a person typed. Reading os.Stdin a byte at a time costs a system call per byte, so you wrap it once and read whole lines out of the buffer.

  • NewReader wraps standard input in a 4096-byte buffer.
  • ReadString reads until it meets the byte you hand it.
  • text keeps the newline you typed, so strings.TrimSpace is the usual next call.
package main

import (
    "bufio"
    "fmt"
    "os"
)

func main() {
    // Create a buffered reader from standard input
    reader := bufio.NewReader(os.Stdin)

    fmt.Print("Enter text: ")

    // Read until the newline character
    text, err := reader.ReadString('\n')
    if err != nil {
        fmt.Println("Error reading:", err)
        return
    }

    fmt.Println("You entered:", text)
}
Terminal
$ go run main.go
Enter text: Hello, gopher
You entered: Hello, gopher

Examples

Reads one line at a time instead of loading the whole file.

file, err := os.Open("access.log")
if err != nil {
    log.Fatal(err)
}
defer file.Close()

scanner := bufio.NewScanner(file)
for scanner.Scan() {
    fmt.Println(scanner.Text())
}
if err := scanner.Err(); err != nil {
    log.Fatal(err)
}
Output
2026-08-06 09:14:02 GET /health 200
2026-08-06 09:14:03 GET /metrics 200
FunctionDescription
NewReader(rd io.Reader) *Reader
r := bufio.NewReader(f)
Wraps rd in a Reader with a 4096-byte default buffer.
NewReaderSize(rd io.Reader, size int) *Reader
r := bufio.NewReaderSize(f, 8192)
Wraps rd in a Reader with a buffer of at least size bytes.
NewWriter(w io.Writer) *Writer
bw := bufio.NewWriter(f)
Wraps w in a Writer with a 4096-byte default buffer.
NewWriterSize(w io.Writer, size int) *Writer
bw := bufio.NewWriterSize(f, 8192)
Wraps w in a Writer with a buffer of at least size bytes.
NewReadWriter(r *Reader, w *Writer) *ReadWriter
rw := bufio.NewReadWriter(r, w)
Combines a Reader and a Writer into one value.
NewScanner(r io.Reader) *Scanner
s := bufio.NewScanner(f)
Wraps r in a Scanner; reading starts on the first Scan call.
(*Reader) Read(p []byte) (n int, err error)
Reads up to len(p) bytes into p; implements io.Reader.
(*Reader) ReadByte() (byte, error)
Reads and returns a single byte.
(*Reader) UnreadByte() error
Un-reads the last byte returned by ReadByte.
(*Reader) ReadRune() (r rune, size int, err error)
Reads and returns a single UTF-8-encoded rune and its byte width.
(*Reader) UnreadRune() error
Un-reads the last rune returned by ReadRune.
(*Reader) ReadLine() (line []byte, isPrefix bool, err error)
Reads one line with the newline stripped; isPrefix reports whether the line didn't fit in the buffer. Deprecated in favor of ReadString or a Scanner.
(*Reader) ReadSlice(delim byte) (line []byte, err error)
line, err := r.ReadSlice('\n')
Reads until delim, returning a slice that points into the internal buffer.
(*Reader) ReadBytes(delim byte) ([]byte, error)
b, err := r.ReadBytes('\n')
Reads until delim, returning a copy of the bytes read, delim included.
(*Reader) ReadString(delim byte) (string, error)
line, err := r.ReadString('\n')
Reads until delim, returning a string, delim included.
(*Reader) Peek(n int) ([]byte, error)
b, err := r.Peek(4)
Returns the next n bytes without advancing the reader; the slice points into the internal buffer.
(*Reader) Discard(n int) (discarded int, err error)
Skips the next n bytes without returning them.
(*Reader) Buffered() int
Returns the number of bytes currently available in the buffer.
(*Reader) Size() int
Returns the size of the underlying buffer in bytes.
(*Reader) Reset(r io.Reader)
Discards buffered data and switches the Reader to read from r.
(*Reader) WriteTo(w io.Writer) (n int64, err error)
Writes all buffered and unread data to w; implements io.WriterTo.
(*Writer) Write(p []byte) (n int, err error)
Buffers p, flushing automatically if it doesn't fit; implements io.Writer.
(*Writer) WriteByte(c byte) error
Buffers a single byte.
(*Writer) WriteRune(r rune) (size int, err error)
Buffers the UTF-8 encoding of rune r.
(*Writer) WriteString(s string) (int, error)
Buffers the contents of s.
(*Writer) Flush() error
err := bw.Flush()
Writes all buffered data to the underlying writer.
(*Writer) Available() int
Returns how many bytes are still unused in the buffer.
(*Writer) AvailableBuffer() []byte
Returns an empty slice with Available() capacity, for appending to before a Write call.
(*Writer) Buffered() int
Returns the number of bytes already buffered.
(*Writer) Size() int
Returns the size of the underlying buffer in bytes.
(*Writer) Reset(w io.Writer)
Discards buffered data and switches the Writer to write to w.
(*Writer) ReadFrom(r io.Reader) (n int64, err error)
Reads from r until EOF, buffering as it goes; implements io.ReaderFrom.
type ReadWriter struct{ *Reader; *Writer }
Embeds a *Reader and a *Writer in one value, so it satisfies both io.Reader and io.Writer.
(*Scanner) Scan() bool
for s.Scan() { ... }
Advances to the next token; returns false at EOF or on error.
(*Scanner) Bytes() []byte
Returns the most recent token as a byte slice, valid only until the next Scan call.
(*Scanner) Text() string
line := s.Text()
Returns the most recent token as a string, valid only until the next Scan call.
(*Scanner) Err() error
if err := s.Err(); err != nil { ... }
Returns the first non-EOF error encountered by Scan.
(*Scanner) Split(split SplitFunc)
s.Split(bufio.ScanWords)
Sets the tokenizer; must be called before the first Scan.
(*Scanner) Buffer(buf []byte, max int)
s.Buffer(buf, 1<<20)
Sets the initial buffer and the maximum token size Scan will allocate.
type SplitFunc func(data []byte, atEOF bool) (advance int, token []byte, err error)
Signature every Scanner tokenizer implements: consume advance bytes of data, optionally emit token.
ScanLines(data, atEOF) (advance int, token []byte, err error)
s.Split(bufio.ScanLines)
Splits on newlines, stripping the line ending. The Scanner's default.
ScanWords(data, atEOF) (advance int, token []byte, err error)
s.Split(bufio.ScanWords)
Splits on runs of whitespace, discarding empty fields.
ScanRunes(data, atEOF) (advance int, token []byte, err error)
s.Split(bufio.ScanRunes)
Splits into individual UTF-8-encoded runes.
ScanBytes(data, atEOF) (advance int, token []byte, err error)
s.Split(bufio.ScanBytes)
Splits into individual bytes.
MaxScanTokenSize
Default maximum size of a single token: 64 * 1024 bytes.
ErrTooLong
Returned by Scan when a token exceeds the buffer's maximum size.
ErrFinalToken
Sentinel a SplitFunc returns as its error to stop Scan after this token without signaling failure.
ErrBufferFull
Returned by ReadSlice when a token doesn't fit in the buffer.
ErrNegativeCount
Returned by Peek when called with a negative count.

Gotchas

  • Peek, ReadSlice, Scanner.Bytes point into the internal buffer, copy them to keep them.
  • Default Scanner caps tokens at 64KB. Use scanner.Buffer for longer lines.
  • Not safe for concurrent use.