strings.TrimSpace不删全角空格和零宽字符不是bug,是设计如此;它仅识别6个ASCII空白符(' '、'\t'、'\n'、'\r'、'\f'、'\v'),对'\u3000'、'\u200b'、'\u00a0'等Unicode空白字符完全无效。

strings.TrimSpace 不删全角空格、零宽字符,这不是 bug,是设计如此
为什么 strings.TrimSpace 删不掉中文空格和零宽字符
它只检查 6 个 ASCII 空白符:' '、'\t'、'\n'、'\r'、'\f'、'\v',对 '\u3000'(全角空格)、'\u200b'(零宽空格)、'\u00a0'(不间断空格)完全无视。
常见错误现象:strings.TrimSpace(" hello ")(首尾是全角空格)返回仍是 " hello ",len() 不变,== "" 判断失败。
- 真实场景多见于:用户从微信/网页/富文本编辑器粘贴输入,登录校验时让
"admin "(带全角空格)绕过非空检查 - 修复建议优先用
strings.Map+unicode.IsSpace,比正则轻量且语义清晰 - 示例函数:
func trimAllSpace(s string) string {
return strings.Map(func(r rune) rune {
if unicode.IsSpace(r) {
return -1
}
return r
}, s)
}
strings.Split 和 strings.Fields 别混用
二者语义完全不同:strings.Split 是“按字面分隔符切”,strings.Fields 是“按任意空白字符切并自动丢空串”。
常见错误现象:strings.Split("a b c", " ") 得到 []string{"a", "", "b", "", "", "c"},遍历时容易触发 panic: index out of range。
立即学习“go语言免费学习笔记(深入)”;
-
strings.Split适合固定分隔符场景:解析 CSV(",")、路径("/")、HTTP 头字段(":") -
strings.Fields适合自然语言或用户输入:命令行参数、配置项列表、日志关键词提取;它把'\r'、'\n'、'\u2028'(行分隔符)也当空白,Windows 换行不会残留 - 若需按逗号分割又过滤空字段,别写
strings.Split(s, ",")后直接遍历,先手动过滤,或改用strings.FieldsFunc(s, func(r rune) bool { return r == ',' })
strings.ReplaceAll 在大字符串高频替换时性能会明显下滑
每次调用都生成新字符串,底层反复分配内存。当原始字符串 >1KB、替换次数多(如循环中)、或用于模板类操作(HTML 渲染、日志清洗)时,GC 压力和 CPU 占用肉眼可见上升。
常见错误现象:火焰图里 runtime.mallocgc 占比突增,QPS 下降。
- 推荐改用
strings.Builder手动拼接,尤其适合已知替换位置的场景 - 记得调用
b.Grow(len(s))预分配容量,避免多次扩容 -
strings.Builder不是 goroutine 安全的,别跨协程复用同一个实例
字符串长度要用对函数:len() ≠ 字符数
len() 返回字节数,不是字符数。UTF-8 编码下,中文、emoji 等多字节字符会让结果远大于直观预期。
常见错误现象:len("你好") 返回 6,但你真正想统计的是 2 个字符;用它做截断或分页逻辑,可能切在 UTF-8 中间,导致乱码。
- 要获取 Unicode 字符数,必须用
utf8.RuneCountInString(s) - 遍历字符串时,用
for _, r := range s而非for i := 0; i ,后者按字节索引,会破坏多字节字符 - 切片操作(如
s[0:3])也是基于字节的,对含中文的字符串直接切极易出错


















