Go 语言中的字符串忽略大小写的相等性判断 与 Unicode Case-folding
对于绝大多数刚学习 Go 语言不久的人来说,如果你问他应该如何忽略大小写判断两个字符串相等,他大有可能写出类似下面这样的代码:
1 2 |
|
或者是用 strings.ToUpper()
,再或者是 strings.ToTitle()
。
这些都是大家的习惯做法,这种写法也没有错误。
但是有没有人会好奇:为什么 Go 语言没有直接提供一个忽略大小写的函数? 先问是不是,再问为什么。 Go 其实是有提供的,只是一开始,很少有人知道罢了。就算后来知道了,可能又忘记名字了。
这个函数就是:func EqualFold(s, t string) bool
。
1
|
|
Go 标准库官方解释:
EqualFold reports whether s and t, interpreted as UTF-8 strings, are equal under Unicode case-folding, which is a more general form of case-insensitivity.
EqualFold 基于 Unicode case-folding 判断两个 UTF-8 字符串是否相等。这是 大小写不敏感比较 的更通用形式。
题外话,Elasticsearch 中也有类似的名词。见:ASCII folding token filter。
所以 Fold 是个什么鬼?
Fold 全称 Case Folding,暂时不知道中文叫什么翻译,大小写折叠?其来源于:Unicode 规范化(Unicode Normalization)。 Case-folding 的提出是为了解决国际语言的大小写问题,而不止是英语(拉丁系,英语中也有少部分外来词是这样)。
比如“简历”这个单词 résumé
的大写,如果只是简单地把 [a-z]
映射成 [A-Z]
,得到的结果是:RéSUMé
。
而实际上,这个单词的大写应该是:RÉSUMÉ
。
为什么 Go 语言引入如此专业的名词,而不直接用类似 "EqualNoCase()" 之类的更加通俗易懂的词语? 我不知道,大概是想让更多的人知道“标准”的存在,能更多地知道制定标准的人所作的工作。
学了 Go 语言之后再回去看 C 语言的字符串忽略大小写的比较:
1 2 |
|
以上写法根本无法应对非拉丁语系语言。
C 语言里面的“字符”在现代看来,应该说是“字节”才正确。
Go 语言里面的 rune
才能算作是一个完整的 Unicode 字符(码点)。