在 GoLang 中如何比较字符串?

当涉及到 Go 字符串比较时,我无法产生一个“真实”的结果。我编写了以下内容来解释这个问题,并附上了输出的屏幕截图

// string comparison in Go
package main
import "fmt"
import "bufio"
import "os"


func main() {
var isLetterA bool


fmt.Println("Enter the letter a")
reader := bufio.NewReader(os.Stdin)
input, _ := reader.ReadString('\n')


if(input == "a") {
isLetterA = true
} else {
isLetterA = false
}


fmt.Println("You entered",input)
fmt.Println("Is it the letter a?",isLetterA)


}

example

173253 次浏览

==是在 Go 中比较字符串的正确操作符。但是,使用 reader.ReadString从 STDIN 读取的字符串不包含 "a",而包含 "a\n"(如果仔细查看,您将看到示例输出中的额外换行)。

您可以使用 strings.TrimRight函数从您的输入中删除尾随的空格:

if strings.TrimRight(input, "\n") == "a" {
// ...
}

对于独立于平台的用户或 Windows 用户,您可以这样做:

导入运行时:

import (
"runtime"
"strings"
)

然后像这样修剪琴弦:

if runtime.GOOS == "windows" {
input = strings.TrimRight(input, "\r\n")
} else {
input = strings.TrimRight(input, "\n")
}

now you can compare it like that:

if strings.Compare(input, "a") == 0 {
//....yourCode
}

当您在多个平台上使用 STDIN 时,这是一种更好的方法。

解释

发生这种情况是因为在 windows 系统中,线路以 "\r\n"结束,这被称为 CRLF,但在 UNIX 系统中,线路以 "\n"结束,这被称为 LF,这就是为什么我们在基于 UNIX 的操作系统中修剪 "\n",而在 windows 系统中修剪 "\r\n"

Golang 字符串内的内容可以使用 ==运算符进行比较。如果结果不如预期,可能会有一些隐藏字符,如 \n\r、空格等。因此,作为一般的经验法则,尝试删除那些使用由 golang 中的 strings包提供的函数。

对于 Instance,可以使用 strings.TrimSpace函数删除空格。还可以定义一个自定义函数来删除所需的任何字符。strings.TrimFunc功能可以给你更多的权力。

Assuming there are no prepending/succeeding whitespace characters, there are still a few ways to assert string equality. Some of those are:

Here are some basic benchmark results (in these tests, strings.EqualFold(.., ..) seems like the most performant choice):

goos: darwin
goarch: amd64
BenchmarkStringOps/both_strings_equal::equality_op-4               10000        182944 ns/op
BenchmarkStringOps/both_strings_equal::strings_equal_fold-4        10000        114371 ns/op
BenchmarkStringOps/both_strings_equal::fold_caser-4                10000       2599013 ns/op
BenchmarkStringOps/both_strings_equal::lower_caser-4               10000       3592486 ns/op


BenchmarkStringOps/one_string_in_caps::equality_op-4               10000        417780 ns/op
BenchmarkStringOps/one_string_in_caps::strings_equal_fold-4        10000        153509 ns/op
BenchmarkStringOps/one_string_in_caps::fold_caser-4                10000       3039782 ns/op
BenchmarkStringOps/one_string_in_caps::lower_caser-4               10000       3861189 ns/op


BenchmarkStringOps/weird_casing_situation::equality_op-4           10000        619104 ns/op
BenchmarkStringOps/weird_casing_situation::strings_equal_fold-4    10000        148489 ns/op
BenchmarkStringOps/weird_casing_situation::fold_caser-4            10000       3603943 ns/op
BenchmarkStringOps/weird_casing_situation::lower_caser-4           10000       3637832 ns/op

因为有很多选项,所以下面是生成基准测试的代码。

package main


import (
"fmt"
"strings"
"testing"


"golang.org/x/text/cases"
"golang.org/x/text/language"
)


func BenchmarkStringOps(b *testing.B) {
foldCaser := cases.Fold()
lowerCaser := cases.Lower(language.English)


tests := []struct{
description string
first, second string
}{
{
description: "both strings equal",
first: "aaaa",
second: "aaaa",
},
{
description: "one string in caps",
first: "aaaa",
second: "AAAA",
},
{
description: "weird casing situation",
first: "aAaA",
second: "AaAa",
},
}


for _, tt := range tests {
b.Run(fmt.Sprintf("%s::equality op", tt.description), func(b *testing.B) {
for i := 0; i < b.N; i++ {
benchmarkStringEqualsOperation(tt.first, tt.second, b)
}
})


b.Run(fmt.Sprintf("%s::strings equal fold", tt.description), func(b *testing.B) {
for i := 0; i < b.N; i++ {
benchmarkStringsEqualFold(tt.first, tt.second, b)
}
})


b.Run(fmt.Sprintf("%s::fold caser", tt.description), func(b *testing.B) {
for i := 0; i < b.N; i++ {
benchmarkStringsFoldCaser(tt.first, tt.second, foldCaser, b)
}
})


b.Run(fmt.Sprintf("%s::lower caser", tt.description), func(b *testing.B) {
for i := 0; i < b.N; i++ {
benchmarkStringsLowerCaser(tt.first, tt.second, lowerCaser, b)
}
})
}
}


func benchmarkStringEqualsOperation(first, second string, b *testing.B) {
for n := 0; n < b.N; n++ {
_ = strings.ToLower(first) == strings.ToLower(second)
}
}


func benchmarkStringsEqualFold(first, second string, b *testing.B) {
for n := 0; n < b.N; n++ {
_ = strings.EqualFold(first, second)
}
}


func benchmarkStringsFoldCaser(first, second string, caser cases.Caser, b *testing.B) {
for n := 0; n < b.N; n++ {
_ = caser.String(first) == caser.String(second)
}
}


func benchmarkStringsLowerCaser(first, second string, caser cases.Caser, b *testing.B) {
for n := 0; n < b.N; n++ {
_ = caser.String(first) == caser.String(second)
}
}