Não sou capaz de produzir um resultado 'verdadeiro' quando se trata de comparação de strings de Go. Escrevi o seguinte para explicar o problema e anexei uma captura de tela da saída
// 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)
}
Respostas:
==
é o operador correto para comparar strings em Go. No entanto, as cadeias de caracteres que você lê de STDIN comreader.ReadString
não contêm"a"
, mas"a\n"
(se você olhar com atenção, verá a quebra de linha extra em sua saída de exemplo).Você pode usar a
strings.TrimRight
função para remover espaços em branco à direita de sua entrada:if strings.TrimRight(input, "\n") == "a" { // ... }
fonte
Para os usuários independentes de plataforma ou usuários do Windows, o que você pode fazer é:
tempo de execução de importação:
import ( "runtime" "strings" )
e, em seguida, apare a string assim:
if runtime.GOOS == "windows" { input = strings.TrimRight(input, "\r\n") } else { input = strings.TrimRight(input, "\n") }
agora você pode compará-lo assim:
if strings.Compare(input, "a") == 0 { //....yourCode }
Esta é uma abordagem melhor quando você usa STDIN em várias plataformas.
Explicação
Isso acontece porque nas linhas do Windows terminam com o
"\r\n"
que é conhecido como CRLF, mas nas linhas do UNIX terminam com o"\n"
que é conhecido como LF e é por isso que aparamos"\n"
nos sistemas operacionais baseados em Unix enquanto aparamos"\r\n"
nas janelas.fonte
Supondo que não haja caracteres de espaço em branco precedentes / posteriores, ainda há algumas maneiras de afirmar a igualdade da string. Alguns deles são:
strings.ToLower(..)
então==
strings.EqualFold(.., ..)
cases#Lower
emparelhado com==
cases#Fold
emparelhado com==
Aqui estão alguns resultados básicos de benchmark (nestes testes,
strings.EqualFold(.., ..)
parece ser a escolha de melhor desempenho):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
Como existem algumas opções, aqui está o código para gerar 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) } }
fonte
O conteúdo dentro das strings no Golang pode ser comparado usando o
==
operador. Se os resultados não são os esperados, pode haver alguns personagens escondidos, como\n
,\r
, espaços, etc. Então, como uma regra geral, tente remover aqueles que utilizam funções fornecidas pelostrings
pacote no golang.Por exemplo, os espaços podem ser removidos usando a
strings.TrimSpace
função. Você também pode definir uma função personalizada para remover qualquer caractere necessário.strings.TrimFunc
função pode lhe dar mais potência.fonte