bufio.scanner按行读取最省心,自动处理换行符、不漏末行、内存可控;需每次先scan再text,循环后检查scanner.err()而非仅io.eof,超长行需提前调buffer。

用 bufio.Scanner 按行读取最省心
绝大多数场景下,直接上 bufio.Scanner 就对了。它自动吞掉 \n 和 \r\n,不漏末行,内存可控,默认单行上限 64KB —— 日志、配置、CSV 行处理全够用。
常见错误是只检查 io.EOF 就结束,却忽略真实 I/O 错误;或者没调 scanner.Err(),导致磁盘满、权限不足等错误被静默吞掉。
- 每次循环必须先调
scanner.Scan(),再用scanner.Text()取内容(不含换行符) - 循环结束后务必检查
scanner.Err(),不是err == io.EOF - 若文件可能含超长行(如导出的 JSON 字段),提前调
scanner.Buffer(make([]byte, 0), 1 扩容缓冲区 - Windows 记事本保存的 UTF-8 文件常带 BOM(
0xEF 0xBB 0xBF),scanner不跳过,第一行开头会多出乱码;需打开文件后手动检测并跳过
bufio.Reader.ReadLine() 适合要原始字节或控制换行格式
当你需要保留原始换行符、做二进制解析、或明确控制截断行为时,bufio.Reader.ReadLine() 比 Scanner 更底层也更灵活,但它返回的是 []byte 切片,且指向内部缓冲区 —— 不复制就存,下一行会覆盖。
- 返回值是
line []byte, isPrefix bool, err error;isPrefix == true表示该行太长被截断,需循环读直到isPrefix == false - 空行返回
[]byte{},不是nil,别用== nil判空 - 若要长期保存某行内容,必须用
append([]byte{}, line...)复制一份 - 它不自动合并
\r\n,也不去掉换行符,line末尾可能含\r或\n
Go 1.24 的 strings.Lines() 和 bytes.Lines() 是新选择
Go 1.24 引入了 strings.Lines() 和 bytes.Lines(),它们返回一个 Seq 迭代器,支持 for range 或回调函数遍历,语义更接近函数式风格。
- 输入是完整字符串或字节切片,所以仍需先加载整个文件 —— 大文件慎用,否则 OOM
-
for _, line := range strings.Lines(s)中只有一个迭代变量line(值),不是索引 - 回调模式下可
return false提前退出,适合“找到即停”类逻辑 - 它按
\n拆分,不识别\r\n,也不跳过 BOM;若源数据来自 Windows,得自己 trim\r
别踩这些坑:BOM、末行丢失、OOM
实际项目里最常卡住人的不是语法,而是这几个隐形雷:
- Windows 下记事本保存的 UTF-8 文件自带 BOM,
bufio.Scanner会把它当普通字符读进来,第一行开头出现类乱码;解决方法是打开文件后先用bytes.HasPrefix(buf[:], []byte{0xEF, 0xBB, 0xBF})判断,再用io.MultiReader跳过 -
bufio.Reader.ReadString('\n')容易漏掉末行 —— 文件结尾无换行符时,ReadString返回io.EOF且不返回最后一段内容;而Scanner和ReadLine都能正确捕获 - 用
os.ReadFile+strings.Split处理大文件,极易触发 OOM;哪怕文件才几百 MB,Go runtime 也可能因内存碎片或 GC 压力崩溃
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











