How do I compare strings in GoLang?

huangapple go评论71阅读模式
英文:

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)

}

How do I compare strings in GoLang?

英文:

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)

}

How do I compare strings in GoLang?

答案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.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:

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 (
&quot;fmt&quot;
&quot;strings&quot;
&quot;testing&quot;
&quot;golang.org/x/text/cases&quot;
&quot;golang.org/x/text/language&quot;
)
func BenchmarkStringOps(b *testing.B) {
foldCaser := cases.Fold()
lowerCaser := cases.Lower(language.English)
tests := []struct{
description string
first, second string
}{
{
description: &quot;both strings equal&quot;,
first: &quot;aaaa&quot;,
second: &quot;aaaa&quot;,
},
{
description: &quot;one string in caps&quot;,
first: &quot;aaaa&quot;,
second: &quot;AAAA&quot;,
},
{
description: &quot;weird casing situation&quot;,
first: &quot;aAaA&quot;,
second: &quot;AaAa&quot;,
},
}
for _, tt := range tests {
b.Run(fmt.Sprintf(&quot;%s::equality op&quot;, tt.description), func(b *testing.B) {
for i := 0; i &lt; b.N; i++ {
benchmarkStringEqualsOperation(tt.first, tt.second, b)
}
})
b.Run(fmt.Sprintf(&quot;%s::strings equal fold&quot;, tt.description), func(b *testing.B) {
for i := 0; i &lt; b.N; i++ {
benchmarkStringsEqualFold(tt.first, tt.second, b)
}
})
b.Run(fmt.Sprintf(&quot;%s::fold caser&quot;, tt.description), func(b *testing.B) {
for i := 0; i &lt; b.N; i++ {
benchmarkStringsFoldCaser(tt.first, tt.second, foldCaser, b)
}
})
b.Run(fmt.Sprintf(&quot;%s::lower caser&quot;, tt.description), func(b *testing.B) {
for i := 0; i &lt; b.N; i++ {
benchmarkStringsLowerCaser(tt.first, tt.second, lowerCaser, b)
}
})
}
}
func benchmarkStringEqualsOperation(first, second string, b *testing.B) {
for n := 0; n &lt; b.N; n++ {
_ = strings.ToLower(first) == strings.ToLower(second)
}
}
func benchmarkStringsEqualFold(first, second string, b *testing.B) {
for n := 0; n &lt; b.N; n++ {
_ = strings.EqualFold(first, second)
}
}
func benchmarkStringsFoldCaser(first, second string, caser cases.Caser, b *testing.B) {
for n := 0; n &lt; b.N; n++ {
_ = caser.String(first) == caser.String(second)
}
}
func benchmarkStringsLowerCaser(first, second string, caser cases.Caser, b *testing.B) {
for n := 0; n &lt; 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.

huangapple
  • 本文由 发表于 2015年12月21日 01:23:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/34383705.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定