
go 中 `bufio.scanner` 默认限制单行长度为 64kb,导致读取宽字段大文件时触发“token too long”错误;应改用 `bufio.reader` 配合 `readstring('\n')` 实现无长度限制的逐行读取。
当处理列数极多(如 200+ 列)、行内容超长的文本文件(例如导出的 CSV 或日志快照)时,bufio.Scanner 的默认行为会成为瓶颈。其内部缓冲区上限由常量 bufio.MaxScanTokenSize = 64 * 1024(即 64KB)硬性约束,一旦某行原始字节长度超过该值(含换行符),scan.Scan() 将返回 false,且 scan.Err() 报 "token too long" —— 此时扫描器已无法继续,后续行被跳过,仅剩首行被读入。
✅ 推荐解决方案:使用 bufio.Reader 替代 Scanner
bufio.Reader 不设单行长度限制,ReadString('\n') 可安全读取任意长度的行(仅受内存约束),语义清晰且控制力更强:
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
file, err := os.Open("t8.txt")
if err != nil {
fmt.Fatal("打开文件失败:", err)
}
defer file.Close()
reader := bufio.NewReader(file)
var result []string
for {
line, err := reader.ReadString('\n')
if err != nil {
// EOF 是正常结束标志(最后一行无 '\n' 时也会在此返回 io.EOF)
if err == bufio.ErrEOF {
// 处理可能存在的末尾无换行符的行
if len(line) > 0 {
result = append(result, line)
}
break
}
fmt.Fatal("读取文件出错:", err)
}
result = append(result, line)
}
fmt.Printf("共读取 %d 行\n", len(result))
}⚠️ 注意事项:
- ReadString('\n') 返回的每行包含结尾的 \n(与 Scanner.Text() 不同),如需纯内容,请用 strings.TrimSpace(line) 或 line[:len(line)-1](确保非空)去除;
- 若文件以 \r\n 结尾(Windows),ReadString('\n') 仍能正确识别并包含 \r\n,建议统一用 strings.TrimRight(line, "\r\n") 做兼容处理;
- 对于超大文件(GB 级),避免一次性 append 全部行到内存切片;可改为流式处理:读一行 → 解析/处理 → 丢弃,以控制内存占用;
- 如需解析 CSV 等结构化格式,推荐直接使用 encoding/csv 包(它底层基于 Reader,已规避 Scanner 限制)。
总之,bufio.Scanner 适用于常规日志或配置类小文件;而面对宽表、长字段、不可控格式的大文件时,bufio.Reader 是更健壮、更可控的底层选择。










