bufio.scanner 自动识别并剥离 \n、\r\n、\r,text() 返回无换行符字符串;但不标准化换行风格,跨平台比较需手动 trimsuffix(line, "\r");readstring 保留分隔符,须清理;bytes() 零分配但内容易覆盖,需及时拷贝或直接使用。

bufio.Scanner 读文件时换行符自动兼容,但别指望它帮你“标准化”
Go 的 bufio.Scanner 默认用 ScanLines 拆分,对 \n、\r\n、\r 都识别为行结束,并自动剥离——你调用 Scanner.Text() 拿到的字符串里**不会有残留的 \r 或 \n**。这是它最省心的地方。
但它不负责“统一格式”,只负责“正确切开”。比如 Windows 文件末尾是 \r\n,Unix 是 \n,Scanner 都能读出最后一行;但如果你后续要对比两行内容是否相等(比如 diff 工具),直接比字符串会失败,因为原始换行符差异可能已影响前一行末尾(例如 "abc\r" vs "abc")。
- 别依赖 Scanner “修复”换行风格:它只是拆分,不是转换器
- 若需跨平台一致的字符串表示,读完后手动用
strings.TrimSuffix(line, "\r")即可,安全且无副作用 - 避免用
strings.TrimSpace()替代:它会吃掉行首尾空格,破坏 YAML/Python 等缩进敏感格式
读用户输入路径时,ReadString('\n') 返回值带 \n 导致 os.Open 失败
从 os.Stdin 读文件名时,常见错误是直接用 bufio.NewReader(os.Stdin).ReadString('\n'),结果得到 "config.txt\n",传给 os.Open 就报 no such file or directory。
这不是换行符“跨平台问题”,而是输入处理疏忽:所有平台下,ReadString 都会把分隔符本身包含在返回字符串里。
- 必须显式清理:
strings.TrimSuffix(input, "\n")或更稳妥的strings.TrimSpace(input) - 不要只 Trim
\n:某些终端或重定向输入可能带\r\n,尤其 Windows 下 - 路径拼接前务必验证:
filepath.Clean()可辅助发现非法字符,但不能替代换行符清理
大文件逐行读取时,Scanner.Bytes() 比 Text() 更省内存
百万行日志里频繁调 Scanner.Text(),GC 压力会明显上升——每次调用都生成新 string header,底层指向同一块 buffer,但 runtime 要为每个 string 分配独立结构体。
Scanner.Bytes() 返回的是内部缓冲区切片,零分配,但**内容会被下一行覆盖**。所以必须立刻处理或拷贝。
- 安全拷贝写法:
line := append([]byte{}, scanner.Bytes()...) - 如果只是做前缀匹配(如
bytes.HasPrefix(line, []byte("ERROR"))),直接用Bytes()即可 - 别在 goroutine 里异步使用
Bytes()结果:buffer 是 Scanner 实例共享的,数据随时失效 - 若需 UTF-8 字符串处理,且行数可控(Text() 仍是最简选择
需要保留原始换行符类型时,得绕过 Scanner 用 bufio.Reader.ReadLine()
当你要生成 patch、高亮差异、或导出带原始格式的文本(比如保持 Windows 脚本可执行性),就不能丢掉换行符信息——Scanner 把它全抹了。
bufio.Reader.ReadLine() 返回原始字节、是否被截断(isPrefix)、以及错误。你可以检查末尾字节判断换行风格:
line, isPrefix, err := reader.ReadLine()
if err != nil && err != io.EOF {
log.Fatal(err)
}
if len(line) > 0 && line[len(line)-1] == '\r' {
// 很可能是 \r\n,但需结合上文判断(单 \r 极少见)
}
-
ReadLine()不自动合并多段,isPrefix为 true 时需循环读并拼接 - 拼接时务必拷贝:
fullLine := append([]byte{}, line...),否则下一次ReadLine()会改写原 slice - 它不处理 BOM,若文件开头有 UTF-8 BOM(
\xEF\xBB\xBF),得手动跳过
\n 后处理;一旦涉及格式保真或协议解析,就得退到 Reader 层自己扛。golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











