Как сравнить строки в 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]()
Ответы
Ответ 1
==
- правильный оператор для сравнения строк в Go. Тем не менее, строки, которые вы читаете из STDIN с помощью reader.ReadString
, не содержат "a"
, но "a\n"
(если вы посмотрите внимательно, вы увидите дополнительный разрыв строки в вашем примере вывода).
Вы можете использовать функцию strings.TrimRight
для удаления конечных пробелов со своего ввода:
if strings.TrimRight(input, "\n") == "a" {
// ...
}
Ответ 2
Для независимых пользователей платформы или пользователей 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, и именно поэтому мы обрезаем "\n"
в операционных системах на основе Unix, а мы обрезаем "\r\n"
на окнах.
Ответ 3
Содержимое внутри строк в Golang можно сравнить с помощью оператора ==
. Если результаты не соответствуют ожидаемым, могут быть некоторые скрытые символы, такие как \n
, \r
, пробелы и т.д. Так что, как правило, попробуйте удалить те, которые используют функции, предоставляемые пакетом strings
в golang.
Для экземпляра пробелы могут быть удалены с помощью функции strings.TrimSpace
. Вы также можете определить пользовательскую функцию для удаления любого нужного вам символа. Функция strings.TrimFunc
может дать вам больше энергии.
Ответ 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)
}
}