unicode.IsLetter 对中文返回 false,因其仅识别 Ll、Lu 等字母子类,而汉字属 Lo 类别;应改用 unicode.Is(unicode.Letter, r) 判断中日韩文字。

unicode.IsLetter 为什么对中文返回 false
它只认 Unicode 字母类(L&、Ll、Lu 等),而中文汉字属于 Lo(Letter, other)类别,不在 unicode.IsLetter 的判定范围内。这不是 bug,是设计如此。
- 用
unicode.IsLetter判断英文、俄文、希腊字母没问题,但对汉字、日文平假名、韩文字母都会返回false - 真正兼容中日韩的判断,得用
unicode.IsOneOf配合字符类别集合,比如unicode.Letter(注意:这是个[]*RangeTable,不是单个类别) - 更直接的做法是:先转成
rune,再查unicode.Is(unicode.Letter, r)—— 这个unicode.Letter才包含Lo、Lm、Lt等全部字母子类
示例:
if unicode.Is(unicode.Letter, r) { /* 中文、英文、emoji 字母都进这里 */ }
区分中文字符和 ASCII 字母要用 unicode.IsHan 还是 unicode.Scripts
标准库根本没有 unicode.IsHan —— 这是常见误解。Go 的 unicode 包不提供按“汉字”“日文”“韩文”这种语义划分的函数,只有按 Unicode 脚本(Script)或区块(Block)的底层支持。
- 判断是否为汉字,正确姿势是:
unicode.Is(unicode.Han, r),其中unicode.Han是预定义的脚本范围表(*unicode.RangeTable) -
unicode.Han覆盖的是 Unicode 的 Han 脚本,包括中日韩越共用汉字,但不含平假名、片假名、谚文(它们分别对应Hiragana、Katakana、Hangul) - 注意:脚本判断依赖 Go 版本,
unicode.Han在 Go 1.19+ 才完整支持扩展汉字区(如 Ext-B/C/D/E),旧版本可能漏判部分生僻字
strings.TrimSpace 处理中文空格失效怎么办
strings.TrimSpace 只删 '\t'、'\n'、'\r'、' ' 和 '\v'、'\f' 这六个 ASCII 控制符,对全角空格( ,U+3000)、零宽空格(U+200B)等完全无效。
立即学习“go语言免费学习笔记(深入)”;
- 要清理广义“空白”,得自己写循环 +
unicode.IsSpace,它识别所有 Unicode 空白字符(含 U+3000、U+2000–U+200A 等) - 注意:
unicode.IsSpace也会把换行、制表符算进去,行为接近但不等价于strings.TrimSpace,需确认业务是否接受 - 若只要删首尾,别用
strings.Map全局替换,而是手写两端扫描逻辑,避免误伤中间内容
简例:
func trimAllSpace(s string) string {
runes := []rune(s)
i, j := 0, len(runes)-1
for i <= j && unicode.IsSpace(runes[i]) { i++ }
for j >= i && unicode.IsSpace(runes[j]) { j-- }
return string(runes[i:j+1])
}
unicode.IsPrint 判定中文标点时意外返回 false
某些中文标点(如 《》【】『』、省略号 …、破折号 —)在 Unicode 中被归类为 Pc(Punctuation, connector)或 Po(Punctuation, other),而 unicode.IsPrint 只放行 L*、M*、N*、P*、S*、Zs 等大类里的“可打印”子集——但它**排除了 Pc**。
- 所以
《(U+300C)、【(U+3010)这类会返回false,尽管它们显然该显示 - 实际做“是否能安全输出”判断,别依赖
IsPrint,改用!unicode.IsControl(r) && !unicode.Is(unicode.Cc, r)更稳妥 - 如果目标是过滤掉不可见控制符(如 U+0000–U+001F),直接检查
unicode.IsControl就够了,IsPrint的语义太窄,容易误伤
这个边界模糊点,常出现在日志清洗、模板渲染前的字符校验环节,一不留神就让合法标点消失。










