bufio.Scanner 是 Go 按行读取文本的首选,自动处理换行符、内存可控、默认单行上限 64KB;避免 os.ReadFile+strings.Split(易 OOM)和 bufio.Reader.ReadString(易漏末行);需检查 scanner.Err() 而非仅 io.EOF;超长行可调用 scanner.Buffer 自定义缓冲区。

用 bufio.Scanner 按行读取最稳妥
绝大多数场景下,bufio.Scanner 是 Go 里按行处理文本文件的首选。它自动处理换行符(\n、\r\n),内存占用可控,且默认单行上限 64KB —— 对普通日志或配置文件完全够用。
常见错误是直接用 os.ReadFile + strings.Split 一次性加载整个文件,大文件容易 OOM;或者用 bufio.Reader.ReadString('\n') 手动处理,结果漏掉最后一行(没换行符时返回 io.EOF 但不报错)。
- 用
scanner.Scan()循环,每次调用后用scanner.Text()获取当前行(不含换行符) - 检查
scanner.Err()判断是否因 I/O 错误提前退出,别只看io.EOF - 若需处理超长行(如某些导出数据),提前调用
scanner.Buffer(make([]byte, 0), 1 扩容缓冲区
file, err := os.Open("data.txt")
if err != nil {
log.Fatal(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
// 处理每一行,例如:strings.TrimSpace(line)
fmt.Println(line)
}
if err := scanner.Err(); err != nil {
log.Fatal(err)
}
bufio.Reader.ReadLine() 适合需要原始字节或控制换行符的场景
bufio.Reader.ReadLine() 返回 []byte 和一个布尔值,表示该行是否被截断(超过缓冲区长度)。它不自动去掉换行符,也不合并 \r\n,适合你明确要保留原始换行格式、或后续做二进制解析的情况。
注意:它返回的是切片,指向底层缓冲区,如果要长期保存某一行内容,必须用 append([]byte{}, line...) 复制一份,否则下一次调用会覆盖。
立即学习“go语言免费学习笔记(深入)”;
- 返回的
isPrefix为true表示行太长被截断,需循环读取直到isPrefix == false - 遇到空行时返回空切片
[]byte{},不是nil,别用== nil判空 - 比
Scanner多一层控制,但也多一层出错可能 —— 比如忘记处理isPrefix
按行读取时忽略 BOM 是个高频坑
Windows 上用记事本保存的 UTF-8 文件常带 BOM(0xEF 0xBB 0xBF),bufio.Scanner 不会自动跳过它,第一行开头会出现乱码字符。这不是编码错误,而是字节被当作文本内容读进来了。
- 打开文件后,先用
bytes.HasPrefix检查前三个字节是否为 BOM,是则用io.MultiReader跳过 - 更简单的方法:用
golang.org/x/text/encoding/unicode包的UTF8.NewDecoder().Bytes()预处理整行(但会失去流式优势) - 如果确定文件来源固定,可在写入端统一禁用 BOM(比如 VS Code 设置
"files.encoding": "utf8"并关掉"files.autoGuessEncoding")
大文件分块读取 + 行边界对齐需手动处理
当文件上百 MB 以上,且每行极短(如 CSV 记录),Scanner 仍够用;但如果单行本身长达几 MB,或你需要严格控制每次系统调用大小(比如限流读取网络响应体),就得绕过 Scanner,用 bufio.Reader.Read() 分块读,再自己找换行符位置。
这时关键难点是:换行符可能被切在两块之间。例如块末尾是 "hello\r",下一块开头是 "\nworld"。必须把上一块末尾的 \r 和下一块开头的 \n 拼起来识别为完整行尾。
- 缓存未完成的行前缀(尤其以
\r结尾时),下一轮读取后拼接再判断 - 别用
bytes.IndexByte(buf, '\n')简单切分 —— 它无法处理\r\n组合 - 实际项目中,优先考虑用现成库如
github.com/apache/arrow/go/arrow/ipc(针对结构化数据)或encoding/csv(针对 CSV),它们内部已处理好边界问题










