
scanner.Text() 方法返回 string 类型,但实际读取内容可能包含不可见字符(如 UTF-8 BOM、Windows 换行符 \r\n 中的 \r),导致字符串比较失败。
`scanner.text()` 方法返回 `string` 类型,但实际读取内容可能包含不可见字符(如 utf-8 bom、windows 换行符 `\r\n` 中的 `\r`),导致字符串比较失败。
在使用 bufio.Scanner 逐行读取文件时,scanner.Text() 的返回值始终是 Go 语言内置的 string 类型。这一点非常明确——它不返回 []byte、不返回带错误的元组,也不做自动 trim 或清理。然而,正是这种“原样返回”的设计,使得开发者容易忽略输入数据中隐藏的非打印字符,从而引发看似诡异的字符串比较失败问题。
最常见的干扰因素包括:
-
UTF-8 BOM(Byte Order Mark):某些编辑器(如 Windows 记事本)保存 UTF-8 文件时会在开头插入
0xEF 0xBB 0xBF三个字节,scanner.Text()会将其作为字符串前缀一并返回,例如"\uFEFF123",导致"123" == line为false; -
Windows 换行符残留
\r:若文件以 CRLF(\r\n)结尾,而系统或工具未正确处理,scanner.Text()虽已自动去掉\n,但不会移除\r——因此line实际为"123\r"; - 其他控制字符(如零宽空格、BOM 变体、尾部空白等)也可能混入。
✅ 正确做法是:在关键比较前主动清理字符串。推荐使用 strings.TrimSpace()(移除首尾空白及 Unicode 空白符,含 \r, \n, \t, U+00A0 等):
import (
"bufio"
"fmt"
"os"
"strings" // ← 别忘了导入
)
// ... 打开文件、创建 scanner 后
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text()) // 安全清理
fmt.Printf("Cleaned: [%q]\n", line)
if line == "123" {
fmt.Println("EQUAL")
}
}
⚠️ 注意事项:
-
strings.TrimSpace不会修改原字符串(Go 中 string 是不可变的),而是返回新字符串; - 若需严格区分空格与业务数据(如密码含尾部空格),应改用
strings.TrimRight(line, "\r\n")精准裁剪; - 检查文件编码与换行符:可用命令行工具验证,例如
file -i input.txt(Linux/macOS)或xxd input.txt | head查看十六进制头; - 长期建议:统一使用
unix换行符(LF)保存文本文件,并在编辑器中禁用 BOM 写入。
总之,scanner.Text() 的类型虽简单(string),但其内容可靠性取决于输入源质量。养成「读即清理」的习惯,是编写健壮文件解析逻辑的关键一步。










