`strings.EqualFold` 不首先进行长度比较是否有原因?

z11*_*11i 3 string unicode go

比较不区分大小写的字符串的常见做法是首先显式检查长度:

if len(a) == len(b) && strings.EqualFold(a, b) { ... }
Run Code Online (Sandbox Code Playgroud)

这似乎是一种解决方法,因为当前的实现仅在耗尽两个输入字符串中的任何一个时才进行长度检查。

是否有理由不首先进行长度检查,无论是性能方面还是其他方面?

icz*_*cza 6

简短的答案是因为 Go 中 2 个字符串可能具有不同的长度,但在简单的 Unicode 大小写折叠下仍然相等(因此首先进行长度比较并不能确定大小写折叠相等性)。

\n

更长的答案是:Go 将字符串作为UTF-8字节存储在内存中,内置len()函数报告 UTF-8 编码的字节数。UTF-8 是一种可变长度字符编码:它可能对单个 unicode 代码点使用不同数量的字节,因此匹配的大小写折叠代码点可能在 UTF-8 中使用不同数量的字节。

\n

看一个例子来证明这一点:

\n
s1, s2 := "\\u017F", "\\u0073"\nfmt.Println(s1, s2)\n\nfmt.Println(len(s1), len(s2), strings.EqualFold(s1, s2))\n
Run Code Online (Sandbox Code Playgroud)\n

这将输出(在Go Playground上尝试):

\n
\xc5\xbf s\n2 1 true\n
Run Code Online (Sandbox Code Playgroud)\n