Wraps an io.Reader or io.Writer to add buffering, which reduces the number of system calls and improves performance. bufio.Scanner is the idiomatic way to read a file line by line in Go.
Import: import "bufio" | Docs: pkg.go.dev/bufio
| Name | Signature / Value | Description |
|---|---|---|
| bufio.NewReader | func NewReader(rd io.Reader) *Reader | Create buffered reader with default 4096-byte buffer |
| bufio.NewReaderSize | func NewReaderSize(rd io.Reader, size int) *Reader | Create buffered reader with custom size |
| r.ReadString | func (b *Reader) ReadString(delim byte) (string, error) | Read until delimiter (inclusive) |
| r.ReadLine | func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error) | Read a single line |
| r.ReadByte | func (b *Reader) ReadByte() (byte, error) | Read and return a single byte |
| r.UnreadByte | func (b *Reader) UnreadByte() error | Un-read the last byte read |
| r.Peek | func (b *Reader) Peek(n int) ([]byte, error) | Return next n bytes without advancing |
| bufio.NewWriter | func NewWriter(w io.Writer) *Writer | Create buffered writer |
| bw.WriteString | func (b *Writer) WriteString(s string) (int, error) | Write string to buffer |
| bw.Flush | func (b *Writer) Flush() error | Flush buffered data to underlying writer |
| bw.WriteByte | func (b *Writer) WriteByte(c byte) error | Write single byte to buffer |
| bufio.NewScanner | func NewScanner(r io.Reader) *Scanner | Create Scanner for convenient line-by-line reading |
| s.Scan | func (s *Scanner) Scan() bool | Advance to next token; return false at EOF or error |
| s.Text | func (s *Scanner) Text() string | Return text of current token as string |
| s.Bytes | func (s *Scanner) Bytes() []byte | Return current token as []byte (avoids allocation) |
| s.Err | func (s *Scanner) Err() error | Return first non-EOF error encountered |
| s.Split | func (s *Scanner) Split(split SplitFunc) | Set split function (default: ScanLines) |
| bufio.ScanLines | func ScanLines(data []byte, atEOF bool) ... | Split function for lines (strips \n) |
| bufio.ScanWords | func ScanWords(data []byte, atEOF bool) ... | Split function for whitespace-delimited words |
| bufio.ScanBytes | func ScanBytes(data []byte, atEOF bool) ... | Split function for individual bytes |
| bufio.Scanner.Buffer | func (s *Scanner) Buffer(buf []byte, max int) | Set initial buffer and max token size |
Save as main.go inside any directory and run with go run main.go. No extra packages to install — all standard library.
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
// --- bufio.Scanner — read stdin line by line ---
fmt.Println("=== Scanner from string ===")
input := "line one\nline two\nline three\n"
scanner := bufio.NewScanner(strings.NewReader(input))
lineNum := 0
for scanner.Scan() {
lineNum++
fmt.Printf(" %d: %s\n", lineNum, scanner.Text())
}
if err := scanner.Err(); err != nil {
fmt.Fprintln(os.Stderr, "scan error:", err)
}
// --- bufio.Scanner — scan words ---
fmt.Println("=== Word scanner ===")
wordScan := bufio.NewScanner(strings.NewReader("Go is awesome"))
wordScan.Split(bufio.ScanWords)
for wordScan.Scan() {
fmt.Printf(" word: %q\n", wordScan.Text())
}
// --- bufio.Writer — buffered file write ---
fmt.Println("=== Buffered file write ===")
f, _ := os.Create("buffered.txt")
bw := bufio.NewWriter(f)
for i := 1; i <= 5; i++ {
fmt.Fprintf(bw, "Line %d: Go buffered I/O\n", i)
}
bw.Flush() // IMPORTANT: flush before closing
f.Close()
// Read back with Scanner
f2, _ := os.Open("buffered.txt")
defer f2.Close()
s2 := bufio.NewScanner(f2)
for s2.Scan() {
fmt.Println(" ", s2.Text())
}
os.Remove("buffered.txt")
}
// go run main.go