룬이란 무엇입니까?


188

runein in 이란 무엇입니까 ?

인터넷 검색을 해왔지만 Golang은 한 줄로만 말합니다 :은의 rune별칭입니다int32 .

그러나 스와핑 케이스처럼 정수가 어떻게 사용됩니까?

다음은 함수 스왑 케이스입니다. 모든 무엇 <=-?

그리고 왜 switch논쟁이 없습니까?

&&말은해야 하고 있지만 무엇입니까 r <= 'z'?

func SwapRune(r rune) rune {
    switch {
    case 'a' <= r && r <= 'z':
        return r - 'a' + 'A'
    case 'A' <= r && r <= 'Z':
        return r - 'A' + 'a'
    default:
        return r
    }
}

그들 대부분은 http://play.golang.org/p/H6wjLZj6lW 에서 온

func SwapCase(str string) string {
    return strings.Map(SwapRune, str)
}

나는 이것이 스왑 된 문자열을 반환 할 수 있도록 매핑하고 있음 rune을 이해 string합니다. 하지만 난 방법을 정확하게 이해하지 않는다 rune또는 byte여기에 작동합니다.


Sidenote : 다른 언어는 말할 것도없이 , 어린 독자들이 영어 단어 "café"다른 사람들을 위해 원하는 것을하지 않습니다 . Go에는 실제로 이러한 종류의 변형에 유용한 변형을 지원하는 라이브러리가 있습니다.
RedGrittyBrick 16:24의

2
"rune"이라는 단어의 출처를 알고 싶은 사람이있는 경우 : en.wikipedia.org/wiki/Runic_(Unicode_block)
Matt Browne

A []rune는 부울, 숫자 또는 문자열 유형으로 설정할 수 있습니다. stackoverflow.com/a/62739051/12817546을 참조하십시오 .
Tom J

답변:


149

룬 리터럴은 32 비트 정수 값입니다 ( 자신의 유형을 변경할 수 있습니다, 그러나 그들이있는 거 유형이 지정되지 않은 상수 ). 유니 코드 코드 포인트를 나타냅니다. 예를 들어, 룬 리터럴 'a'은 실제로 숫자 97입니다.

따라서 프로그램은 다음과 거의 같습니다.

package main

import "fmt"

func SwapRune(r rune) rune {
    switch {
    case 97 <= r && r <= 122:
        return r - 32
    case 65 <= r && r <= 90:
        return r + 32
    default:
        return r
    }
}

func main() {
    fmt.Println(SwapRune('a'))
}

해당 범위의 ASCII 와 동일한 유니 코드 매핑을 살펴 보려면 분명해야합니다 . 또한 32는 실제로 문자의 대문자와 소문자 코드 포인트 사이의 오프셋입니다. 그래서 추가하여 32하는 'A', 당신이 얻을 'a'반대 및 부사장.


12
이것은 분명히 'ı'(U + 0131)와 같은 더 복잡한 경우는 물론 ASCII 문자에만 적용되며 'ä'와 같은 추가 문자에는 적용되지 않습니다. Go에는와 같은 소문자에 매핑 할 수있는 특수 기능이 있습니다 unicode.ToLower(r rune) rune.
topskip

2
그리고 az뿐만 아니라 모든 코드 포인트에서 작동하는 SwapCase 함수를 사용하여 @topskip의 정답에 추가하려면 다음과 같이하십시오.func SwapRune(r rune) rune { if unicode.IsUpper(r) { r = unicode.ToLower(r) } else { r = unicode.ToUpper(r) }; return r }
ANisus

22
룬은 int32 값입니다. 이것이 전체 답변입니다. 그들은 "매핑" 되지 않습니다 .
thwd

@AlixAxel : SimpleFold의 동작은 본질적으로 동일합니다 (대부분의 룬에는 ToLower와 ToUpper도 사용합니다). DZ-> Dz, Dz-> dz, dz-> DZ와 같이 다른 경우가 있습니다. 내 SwapRune 대신 DZ-> dz, Dz-> DZ, dz-> DZ로 이동합니다. 나는 당신의 제안을 더 좋아합니다 :)
ANisus

3
룬 문자는 C 문자와 비슷합니까?
Kenny Worden

53

Go lang 릴리스 정보 : http://golang.org/doc/go1#rune

룬은 유형입니다. 32 비트를 차지하며 유니 코드 CodePoint 를 나타냅니다 . 'ASCII'로 인코딩 된 영어 문자 세트는 128 개의 코드 포인트가 있습니다. 따라서 바이트 (8 비트) 안에 들어갈 수 있습니다. 이 (잘못된) 가정에서 C는 문자를 'bytes'로 char, 'strings'를 '문자 순서'로 취급했습니다 char*.

하지만 그거 알아. 'abcde ..'기호 외에 인간이 발명 한 다른 기호가 많이 있습니다. 그리고 그것을 인코딩하기 위해 32 비트가 필요한 것이 너무 많습니다.

golang에서 a string는 일련의 bytes입니다. 그러나 여러 바이트가 룬 코드 포인트를 나타낼 수 있으므로 문자열 값에도 룬이 포함될 수 있습니다. 따라서으로 변환 []rune하거나 그 반대로 변환 할 수 있습니다 .

유니 코드 패키지 http://golang.org/pkg/unicode/ 는 풍부한 도전을 맛볼 수 있습니다.


6
최근 유니 코드 6.3에는 110,000 개가 넘는 기호가 정의되어 있습니다. 이를 위해서는 각 코드 포인트를 21 비트 이상으로 표현해야하므로 a rune와 비슷 int32하며 많은 비트가 있습니다.
Rick-777

2
당신은 "a string는 일련의 runes"라고 말합니다-나는 그것이 사실이라고 생각하지 않습니까? 블로그 이동 : "문자열은 단지 바이트입니다"; Go lang spec : "문자열 값은 바이트 시퀀스입니다 (빈 문자열)"
Chris Martin

1
나는 아직도 혼란 스럽습니다. 그래서 string은 룬 배열이나 바이트 배열입니까? 그들은 상호 교환이 가능합니까?
gogofan

1
@prvn 잘못되었습니다. 이미지가 바이트 시퀀스가 ​​아니라 픽셀 시퀀스라고 말하는 것과 같습니다. 그러나 실제로 그 아래에는 일련의 바이트가 있습니다. 문자열은 룬이 아닌 일련의 바이트입니다. 사양을 읽으십시오 .
Inanc Gumus

1
@prvn하지만 말할 수는 없습니다 not bytes. "문자열은 룬과 바이트로 구성된 룬으로 구성되어 있습니다"라고 말할 수 있습니다. 그리고 다시. 완전히 사실이 아닙니다.
Inanc Gumus

28

나는 평신도가 이해할 수 있도록 내 언어를 단순하게 유지하려고 노력했습니다 rune.

룬은 캐릭터입니다. 그게 다야.

단일 문자입니다. 세계 어느 곳에서나 모든 언어의 알파벳 문자입니다.

우리가 사용하는 문자열을 얻으려면

double-quotes ""

또는

back-ticks ``

문자열은 룬과 다릅니다. 룬에서 우리는 사용합니다

single-quotes ''

이제 룬은 int32... 의 별칭입니다 . 어?

룬이 별명 인 이유는 int32다음과 같은 코딩 체계를 사용하기 때문입니다. 여기에 이미지 설명을 입력하십시오

각 문자는 어떤 숫자에 매핑되므로 우리가 저장하고있는 숫자입니다. 예를 들어, A는 매핑 97 우리는 그 번호를 저장할 때 그것은 단지 수의 등의 방법 룬은 INT32의 별칭이다. 그러나 숫자가 아닙니다. 32 개의 '0과 1'또는 '4'바이트의 숫자입니다. (참고 : UTF-8은 4 바이트 인코딩 체계입니다)

룬은 문자열과 어떤 관련이 있습니까?

문자열은 룬의 모음입니다. 다음 코드에서

    package main

    import (
        "fmt"
    )

    func main() {
        fmt.Println([]byte("Hello"))
    }

문자열을 바이트 스트림으로 변환하려고합니다. 출력은 다음과 같습니다.

[72 101 108 108 111]

해당 문자열을 구성하는 각 바이트가 룬임을 알 수 있습니다.


2
A string is not a collection of runes이것은 엄밀히 말하면 정확하지 않습니다. 대신, string은 utf8로 인코딩 된 바이트 슬라이스입니다. 문자열의 각 문자는 실제로 1 ~ 3 바이트가 걸리며 각 룬은 4 바이트가 필요합니다. 문자열과 [] 룬 사이에서 변환 할 수 있지만 서로 다릅니다.
Eric Wang

2
룬은 문자가 아니며 룬은 유니 코드 코드 포인트를 나타냅니다. 코드 포인트가 반드시 한 문자를 가리키는 것은 아닙니다.
Inanc Gumus

가치가 그 예 "룬도 INT32의 별칭입니다"추가,하지만 당신은 문자열 변환이 잘못된 길로가는 55,296 뭔가를 칠 경우는 ... 그것은 가난한 사람의 압축을위한 유용 의미하지 않는다 : 이동 놀이터
kubanczyk

27

fabrizioM의 답변에 의견을 게시 할만 큼 평판이 충분하지 않으므로 대신 여기에 게시해야합니다.

파브리 치오의 대답은 대체로 정확하고 분명히 문제의 본질을 포착했습니다.

문자열은 반드시 일련의 룬일 필요 는 없습니다 . 그것은 '바이트 슬라이스' 에 대한 래퍼 이며, 슬라이스 는 Go 배열에 대한 래퍼입니다. 이것이 어떤 차이가 있습니까?

유형은 반드시 비트 × * 32 몇개있을 것이다 룬 종류의 값의 시퀀스를 의미 반드시 32 비트 값이다. 바이트 시퀀스 인 문자열은 길이가 x * 8 비트입니다. 모든 문자열이 실제로 유니 코드 인 경우이 차이는 영향을 미치지 않습니다. 그러나 문자열은 바이트 조각 이므로 Go는 ASCII 또는 다른 임의의 바이트 인코딩을 사용할 수 있습니다.

그러나 문자열 리터럴은 UTF-8로 인코딩 된 소스에 작성해야합니다.

정보 출처 : http://blog.golang.org/strings


1
좋은 지적 ! 각 룬에는 4 바이트가 필요하지만 문자열의 각 문자는 utf8로 인코딩되므로 최대 1-3 바이트입니다.
Eric Wang

16

(답변보다 여전히 차이 및 관계를 명시하지 않았다 느낌이있어 string[]rune내가 예와 다른 대답을 추가 할 것이다, 그래서 매우 명확합니다.)

으로 @Strangework의 대답은 말했다, string그리고 []rune조용한 다르다.

차이점- string& []rune:

  • string value읽기 전용 바이트 슬라이스입니다. 그리고 문자열 리터럴은 utf-8로 인코딩됩니다. 각 문자는 string실제로 1 ~ 3 바이트 가 걸리고 각 문자 rune4 바이트 가 걸립니다
  • 의 경우 및 인덱스는 string모두 len()바이트를 기반으로합니다.
  • 의 경우 및 인덱스는 []rune모두 len()룬 (또는 int32)을 기반으로합니다.

관계- string& []rune:

  • 에서 string로 변환하면 []rune해당 문자열의 각 utf-8 문자가로 변경 rune됩니다.
  • 마찬가지로 역변환에서에서 []rune로 변환 할 때 string각각 rune은의 utf-8 문자가됩니다 string.

팁 :

  • string와 사이를 변환 할 수 []rune있지만 유형과 전체 크기가 서로 다릅니다.

(더 명확하게 보여주는 예를 추가하겠습니다.)


암호

string_rune_compare.go :

// string & rune compare,
package main

import "fmt"

// string & rune compare,
func stringAndRuneCompare() {
    // string,
    s := "hello你好"

    fmt.Printf("%s, type: %T, len: %d\n", s, s, len(s))
    fmt.Printf("s[%d]: %v, type: %T\n", 0, s[0], s[0])
    li := len(s) - 1 // last index,
    fmt.Printf("s[%d]: %v, type: %T\n\n", li, s[li], s[li])

    // []rune
    rs := []rune(s)
    fmt.Printf("%v, type: %T, len: %d\n", rs, rs, len(rs))
}

func main() {
    stringAndRuneCompare()
}

실행 :

string_rune_compare.go를 실행하십시오.

산출:

hello你好, type: string, len: 11
s[0]: 104, type: uint8
s[10]: 189, type: uint8

[104 101 108 108 111 20320 22909], type: []int32, len: 7

설명:

  • hello你好처음 5 개의 문자는 각각 1 바이트 만 사용하고 마지막 2 개의 중국어 문자는 각각 3 바이트를 사용하므로 문자열의 길이는 11입니다.

    • 그러므로, total bytes = 5 * 1 + 2 * 3 = 11
    • 이후 len()문자열에서 바이트 단위에 기초 따라서, 첫번째 줄은 인쇄len: 11
    • 문자열의 인덱스도 바이트를 기반으로하기 때문에 다음 두 줄은 유형의 값을 인쇄합니다 uint8( byte이는 별칭 유형이므로 uint8계속).
  • 변환 할 때 string[]rune, 그것은 따라서 7 개 UTF8의 문자, 7 룬을 발견했다.

    • 이후 len()에이 []rune룬에 기초하고, 따라서 마지막 라인이 인쇄 len: 7.
    • []rune인덱스를 통해 조작하면 룬의 기본에 액세스합니다.
      각 룬은 원래 문자열의 utf8 문자에서 왔으므로 len()인덱스 작업 []rune은 utf8 문자를 기반으로 한다고 말할 수 있습니다 .

"문자열의 경우 len ()과 index는 모두 바이트를 기반으로합니다." 좀 더 설명해 주시겠습니까? 내가 할 때 fmt.Println("hello你好"[0])바이트 대신 실제 UTF-8 코드 포인트를 반환합니다.
Julian

@Julian 대답에서 프로그램의 출력을 살펴보십시오. for s[0]print s[0]: 104, type: uint8, type is uint8, its its byte. hutf-8 과 같은 ASCII 문자 도 단일 바이트를 사용하여이를 나타내므로 코드 포인트는 단일 바이트와 동일합니다. 그러나와 같은 중국어 문자의 경우 3 바이트를 사용합니다.
Eric Wang

명확화 예. 여기에 stackoverflow.com/a/62739051/12817546을 인용했습니다 .
톰 J

7

다른 사람들은 룬과 관련된 부분을 다루었으므로 그것에 대해 이야기하지 않을 것입니다.

그러나 switch논쟁 이 없는 것과 관련된 질문도 있습니다 . 이것은 Golang에서 switch표현식이없는 경우 if / else 논리를 표현하는 대체 방법 이기 때문입니다 . 예를 들어 다음과 같이 작성하십시오.

t := time.Now()
switch {
case t.Hour() < 12:
    fmt.Println("It's before noon")
default:
    fmt.Println("It's after noon")
}

이것을 쓰는 것과 같습니다 :

t := time.Now()
if t.Hour() < 12 {
    fmt.Println("It's before noon")
} else {
    fmt.Println("It's after noon")
}

자세한 내용은 여기를 참조 하십시오 .


0

룬은 int32 값이므로 유니 코드 코드 포인트를 나타내는 데 사용되는 Go 유형입니다. 유니 코드 코드 포인트 또는 코드 위치는 일반적으로 단일 유니 코드 문자를 나타내는 데 사용되는 숫자 값입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.