Go

What are the pitfalls of bufio.Scanner and bufio.Writer?

Question 460MediumGo 1.22 to 1.25

Scanner: the default max token size is 64 KB (bufio.MaxScanTokenSize). A longer line makes Scan() return false, and unless you check sc.Err() (which is bufio.ErrTooLong) you silently process a truncated file. Also, sc.Bytes() returns a slice into the internal buffer that is overwritten on the next Scan — copy it if you keep it.

sc := bufio.NewScanner(f)
sc.Buffer(make([]byte, 0, 64*1024), 10*1024*1024) // allow 10 MB lines
var lines [][]byte
for sc.Scan() {
	lines = append(lines, bytes.Clone(sc.Bytes())) // copy!
}
if err := sc.Err(); err != nil {
	return err
}

For arbitrary-length lines, use bufio.Reader.ReadString('\n') or ReadLine. sc.Split(bufio.ScanWords) changes tokenization.

Writer: data sits in a 4 KB buffer until full; forgetting Flush() loses the tail. Errors are sticky: once a write fails, all subsequent writes return the same error, so checking Flush's error is enough.

w := bufio.NewWriter(f)
for _, l := range lines {
	w.Write(l)
	w.WriteByte('\n')
}
if err := w.Flush(); err != nil {
	return err
}
return f.Close() // Close error matters for writes, too

More on Standard Library, HTTP & Systems Design in Go

All 35 Standard Library, HTTP & Systems Design in Go questions