strings.trimspace 不能当清洗用,因其仅删除首尾 unicode 空白,对中间的 、 、多空格混杂完全无效;真正语义级清洗需先压缩连续空白为单个空格(正则 \s+ 或双指针),再 trimspace,并显式处理 u00a0、u200b 等非 s 覆盖的 unicode 空白及 bom。

strings.TrimSpace 为什么不能当清洗用
它只删首尾空白,对中间的 、
、多个空格混杂完全没反应。比如输入 "a b
c",输出还是原样——这不是清洗,是假装处理了。
真正要的是语义级规整:所有连续空白(含 Unicode 空白)压缩成单个空格,再 trim 首尾。
- 简单场景用
regexp.MustCompile(`s+`).ReplaceAllString(s, " "),再套一层strings.TrimSpace - 性能敏感时(如日志流每秒百万行),别用正则,手写双指针遍历:只保留第一个空白,跳过后续连续空白
-
s不匹配u00A0(NBSP)、u200B(零宽空格)等 Unicode 空白,需显式补进正则或在双指针逻辑里判断
读 CSV 或日志前必须处理 BOM
Windows 记事本、Excel 导出的文件常带 UTF-8 BOM(),csv.Reader 和 bufio.Scanner 都不自动跳过,会导致首字段变成 "ufeffname",后续字段全错位。
- 用
bytes.HasPrefix(data, []byte{0xEF, 0xBB, 0xBF})检测,存在就切片跳过前 3 字节 - 若用
bufio.NewReader,读第一块后调reader.Reset(bytes.TrimPrefix(buf, []byte{0xEF, 0xBB, 0xBF})) - 别指望
encoding/binary.Read自动处理——它只认固定长度头,不适用于文本流
按列提取时 strings.Fields 和 strings.Split 怎么选
选错就丢列、错位、乱码。核心看分隔符是否“严格”:
-
strings.Fields:把所有连续空白(空格//)当一个分隔符,适合自由格式日志,但会吞空列("a c"→["a", "c"]) -
strings.Split(line, " "):只按制表符切,能保空列,但遇到空格+制表符混用就失效 - 真实 CSV?直接用
encoding/csv包,它处理引号、换行、转义,别硬写 - 取第 N 列前必须检查长度:
if len(fields) > n { value = fields[n] },否则panic: index out of range
scanner.Scan() 为什么突然 panic: "scan: too long"
默认单行上限 64KB,遇到超长日志行、拼错的 JSON 或无换行的 base64 字段,直接崩溃且无法恢复。
- 调
scanner.Buffer(make([]byte, 64*1024), 10*1024*1024)扩大最大 token 长度(第二参数设为 10MB) - 更稳的做法是弃用
Scan,改用bufio.Reader.ReadLine():它返回[]byte和isPrefix,可手动拼接跨缓冲区长行 - 若清洗逻辑允许(如纯字符串替换),直接用
io.Copy+bytes.ReplaceAll流式处理,绕过“行”概念
BOM 检测和跳过必须放在任何解析逻辑之前;双指针清洗比正则快一个数量级,但得自己处理 Unicode 空白;列提取永远先判空再取索引——这些不是可选项,是每次打开文件就要写的前置动作。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











