[go] 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)

}

예



답변

==Go에서 문자열을 비교하는 올바른 연산자입니다. 그러나, 문자열은 당신과 함께 STDIN에서 읽어 reader.ReadString포함되어 있지 않습니다 "a"만, "a\n"(당신이 자세히 본다면, 당신은 당신의 예제 출력에서 여분의 줄 바꿈을 볼 수 있습니다).

strings.TrimRight함수를 사용 하여 입력에서 후행 공백을 제거 할 수 있습니다 .

if strings.TrimRight(input, "\n") == "a" {
    // ...
}


답변

플랫폼 독립 사용자 또는 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을 사용할 때 더 나은 접근 방식입니다.

설명

이것은 창 "\r\n"에서 CRLF로 알려진 행이 끝나기 때문에 발생 하지만 UNIX 행 "\n"에서는 LF로 알려진 것으로 끝나기 때문에 창 "\n"을 자르는 동안 유닉스 기반 운영 체제에서 자르기 때문 "\r\n"입니다.


답변

선행 / 후속 공백 문자가 없다고 가정하면 문자열 동등성을 주장하는 몇 가지 방법이 있습니다. 그중 일부는 다음과 같습니다.

다음은 몇 가지 기본적인 벤치 마크 결과입니다 (이 테스트 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)
    }
}


답변

Golang의 문자열 내부 내용은 ==연산자를 사용하여 비교할 수 있습니다 . 결과는 예상대로되지 않으면 같은 몇 가지 숨겨진 문자가있을 수 있습니다 \n, \r그래서는 일반적인 경험에 의해 제공 기능을 사용하여 해당 제거하려고, 공간 등 stringsgolang에 패키지를.

예를 들어, strings.TrimSpace함수를 사용하여 공백을 제거 할 수 있습니다 . 필요한 문자를 제거하기 위해 사용자 정의 함수를 정의 할 수도 있습니다. strings.TrimFunc기능은 당신에게 더 많은 힘을 줄 수 있습니다.


답변