英文:
How do I compare strings in GoLang?
问题
我在处理Go字符串比较时无法产生一个“真实”的结果。我写了以下内容来解释这个问题,并附上了输出的截图。
// Go中的字符串比较
package main
import "fmt"
import "bufio"
import "os"
func main() {
var isLetterA bool
fmt.Println("输入字母a")
reader := bufio.NewReader(os.Stdin)
input, _ := reader.ReadString('\n')
if(input == "a") {
isLetterA = true
} else {
isLetterA = false
}
fmt.Println("你输入了",input)
fmt.Println("它是字母a吗?",isLetterA)
}
英文:
I am unable to produce a 'true' result when it comes to Go string comparison. I wrote the following to explain the issue and attached a screenshot of the output
// 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)
}
答案1
得分: 158
==
是在 Go 语言中比较字符串的正确运算符。然而,使用 reader.ReadString
从 STDIN 读取的字符串不是包含 "a"
,而是包含 "a\n"
(如果你仔细观察,你会看到示例输出中有额外的换行符)。
你可以使用 strings.TrimRight
函数来删除输入中的尾部空白字符:
if strings.TrimRight(input, "\n") == "a" {
// ...
}
英文:
==
is the correct operator to compare strings in Go. However, the strings that you read from STDIN with reader.ReadString
do not contain "a"
, but "a\n"
(if you look closely, you'll see the extra line break in your example output).
You can use the strings.TrimRight
function to remove trailing whitespaces from your input:
if strings.TrimRight(input, "\n") == "a" {
// ...
}
答案2
得分: 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
}
当你在多个平台上使用标准输入时,这是一种更好的方法。
解释
这是因为在Windows上,行以"\r\n"
结尾,这被称为CRLF,而在UNIX上,行以"\n"
结尾,这被称为LF,所以我们在基于UNIX的操作系统上修剪"\n"
,而在Windows上修剪"\r\n"
。
英文:
For the Platform Independent Users or Windows users, what you can do is:
import runtime:
import (
"runtime"
"strings"
)
and then trim the string like this:
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
}
This is a better approach when you're making use of STDIN on multiple platforms.
Explanation
This happens because on windows lines end with "\r\n"
which is known as CRLF, but on UNIX lines end with "\n"
which is known as LF and that's why we trim "\n"
on unix based operating systems while we trim "\r\n"
on windows.
答案3
得分: 4
假设没有前导/后续的空白字符,有几种方法可以断言字符串的相等性。其中一些方法包括:
strings.ToLower(..)
然后使用==
运算符strings.EqualFold(.., ..)
cases#Lower
结合==
运算符cases#Fold
结合==
运算符
以下是一些基本的基准测试结果(在这些测试中,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)
}
}
希望对你有所帮助!
英文:
Assuming there are no prepending/succeeding whitespace characters, there are still a few ways to assert string equality. Some of those are:
strings.ToLower(..)
then==
strings.EqualFold(.., ..)
cases#Lower
paired with==
cases#Fold
paired with==
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
Since there are quite a few options, so here's the code to generate benchmarks.
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)
}
}
答案4
得分: 1
在Golang中,可以使用==
运算符来比较字符串中的内容。如果结果与预期不符,可能存在一些隐藏字符,如\n
、\r
、空格等。因此,作为一个经验法则,可以尝试使用Golang中strings
包提供的函数来去除这些字符。
例如,可以使用strings.TrimSpace
函数来去除空格。你还可以定义一个自定义函数来去除任何你需要的字符。strings.TrimFunc
函数可以给你更多的控制权。
英文:
The content inside strings in Golang can be compared using ==
operator. If the results are not as expected there may be some hidden characters like \n
, \r
, spaces, etc. So as a general rule of thumb, try removing those using functions provided by strings
package in golang.
For Instance, spaces can be removed using strings.TrimSpace
function. You can also define a custom function to remove any character you need. strings.TrimFunc
function can give you more power.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论