如何在GoLang中比较字符串?

124

在 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)

}

示例

4个回答

162

== 是在 Go 语言中比较字符串的正确运算符。然而,使用 reader.ReadString 从 STDIN 读取的字符串不包含 "a",而是包含 "a\n"(如果你仔细观察,会发现在示例输出中有额外的换行符)。

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

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

13
对于平台无关用户或Windows用户,你可以做以下操作:

导入运行时:

import (
    "runtime"
    "strings"
)

然后像这样修剪字符串:

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

现在你可以这样进行比较:

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

如果您在多个平台上使用STDIN,则这是更好的方法。

解释

这是因为在Windows上,行末以"\r\n"结尾,即CRLF,而在UNIX上,行末以"\n"结尾,即LF。这就是为什么我们在基于UNIX的操作系统上修剪"\n",而在Windows上修剪"\r\n"的原因。


5
不需要区分。第二个参数是切割集,而不是后缀,切割集中的任何字符都将被裁剪,顺序/组合不限。在这两者上裁剪 "\r\n" 就足够了。 - Jason Carlson

5
假设没有前导/后续的空格字符,有几种方法可以断言字符串相等性。其中一些包括: 以下是一些基本的基准测试结果(在这些测试中,strings.EqualFold(.., ..) 似乎是性能最高的选择):
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)
    }
}

1
在Golang中,字符串内的内容可以使用“==”运算符进行比较。如果结果不如预期,可能存在一些隐藏字符,例如“\n”、“\r”、空格等。因此,作为一个常规的经验法则,尝试使用Golang提供的“strings”包中的函数来删除这些字符。
例如,可以使用“strings.TrimSpace”函数删除空格。您还可以定义一个自定义函数来删除任何所需的字符。“strings.TrimFunc”函数可以给您更多的功能。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接