为什么我的 Go 语言字符串比较不按预期工作?

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

Why is my go lang string comparison not working as expected?

问题

我正在尝试使用Go,并编写了一些代码来检查输入是否为yn

reader := bufio.NewReader(os.Stdin)
fmt.Print("(y / n): ")
text, _ := reader.ReadString('\n')
text = strings.ToLower(text)

if strings.Compare(text, "y") == 0 {
    fmt.Println("True")
} else {
    fmt.Println("Else")
}

当我运行这段代码并输入y(然后按回车键),我期望看到True,但实际上我得到了Else - 有人能看出问题在哪里吗?

英文:

I am dipping my toe with Go and have written some code to check if y or n is input:

reader := bufio.NewReader(os.Stdin)
fmt.Print("(y / n): ")
text, _ := reader.ReadString('\n')
text = strings.ToLower(text)

if strings.Compare(text, "y") == 0 { 
	fmt.Println("True")
} else {
	fmt.Println("Else")
}

When I run this code & type y (and press enter) I expect to see True but I get Else - can anyone see why?

答案1

得分: 5

你可能想要的是这样的代码:

reader := bufio.NewReader(os.Stdin)
fmt.Print("(y / n): ")
text, _ := reader.ReadString('\n')
text = strings.ToLower(text[0:len(text)-1])

if strings.Compare(text, "y") == 0 { 
   fmt.Println("True")
} else {
   fmt.Println("Else")
}

如上面的注释所说,ReadString() 函数返回的字符串包含了分隔符。所以你得到的是 "y\n",与 "y" 进行比较的结果是 false。(你可能更愿意使用 Trim() 函数来去除输入两侧的所有空白字符!)

编辑:Trim() 的建议应始终优先于原始建议。否则会产生非可移植的代码,正如本答案的评论中所示。完整的修订代码如下:

reader := bufio.NewReader(os.Stdin)
fmt.Print("(y / n): ")
text, _ := reader.ReadString('\n')	
text = strings.ToLower(strings.Trim(text," \r\n"))

if strings.Compare(text, "y") == 0 { 
   fmt.Println("True")
} else {
   fmt.Println("Else")
}
英文:

You most likely want something like:

reader := bufio.NewReader(os.Stdin)
fmt.Print("(y / n): ")
text, _ := reader.ReadString('\n')
text = strings.ToLower(text[0:len(text)-1])

if strings.Compare(text, "y") == 0 { 
   fmt.Println("True")
} else {
   fmt.Println("Else")
}

As the comment above says, ReadString() returns the delimiter as part of the string. So you're getting "y\n" and comparing to "y" - the result is false. (You might rather use the Trim() function to remove all whitespace from either side of the input,instead!)

Edit: The Trim() suggestion should always be preferred over the original suggestion. To do otherwise produces non-portable code, as illustrated in the comments to this answer. The complete revised code:

reader := bufio.NewReader(os.Stdin)
fmt.Print("(y / n): ")
text, _ := reader.ReadString('\n')	
text = strings.ToLower(strings.Trim(text," \r\n"))

if strings.Compare(text, "y") == 0 { 
   fmt.Println("True")
} else {
   fmt.Println("Else")
}

答案2

得分: 3

正如@TimCooper在评论中指出的那样,ReadString函数会读取输入中第一个分隔符(delim)之前的数据,并返回包含该数据和分隔符的字符串。因此,当你使用\n作为分隔符时,它会包含在读取的文本中,所以在进行比较或去除时需要考虑这一点。

正如在其他答案的讨论中所揭示的那样,仅仅去除\n是不够的。这可能是因为来自标准输入(stdin)的用户输入在不同操作系统上的行尾符可能不同。在UNIX中是\n,在Windows中是\r\n
这里是一个更具可移植性的解决方案:

if strings.TrimRight(text, "\r\n") == "y" {

我还将使用strings.Compare改为了直接、简单地与"y"进行比较。

英文:

As @TimCooper pointed out in a comment,
"ReadString reads until the first occurrence of delim in the input, returning a string containing the data up to and including the delimiter".
That means, as your delimiter is \n, it will get included in the text read, so you need to consider that when making comparisons, or strip it out.

As revealed by the discussion on the other answer, simply stripping \n is not enough. This is probably because the line ending of user input from stdin may be different depending on the operating system. In UNIX it's \n, in Windows it's \r\n.
Here's a more portable solution:

if strings.TrimRight(text, "\r\n") == "y" {

I also changed the use of strings.Compare to a more direct, simpler comparison with "y" directly.

huangapple
  • 本文由 发表于 2016年11月6日 04:39:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/40442971.html
匿名

发表评论

匿名网友

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

确定