web-dev-qa-db-ja.com

ルーンとは何ですか?

Goのruneとは何ですか?

私はグーグルをしてきましたが、Golangは1行でしか言いません:runeint32のエイリアスです。

しかし、スワッピングのように整数が使用されるのはなぜですか?

以下は関数スワップケースです。すべての<=-とは何ですか?

そして、なぜswitchに引数がないのですか?

&&andを意味するはずですが、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)
}

私は、これがrunestringにマッピングし、交換された文字列を返すことができることを理解しています。しかし、ここでruneまたはbyteが正確にどのように機能するかはわかりません。

150
user2671513

Runeリテラルは単なる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'))
}

Unicodeマッピングを確認する場合、その範囲の ASCII と同じであることが明らかです。さらに、32は実際には文字の大文字と小文字のコードポイント間のオフセットです。したがって、32'A'に追加すると、'a'が得られ、その逆も同様です。

122
topskip

Go langリリースノートから: http://golang.org/doc/go1#rune

ルーンはタイプです。 32ビットを占有し、 nicodeCodePoint を表すことを意図しています。類推として、「ASCII」でエンコードされた英語の文字セットには128個のコードポイントがあります。したがって、バイト(8ビット)内に収めることができます。この(誤った)仮定から、Cは文字を「バイト」charとして扱い、「文字列」を「文字のシーケンス」char*として扱いました。

しかし、何を推測します。 「abcde ..」シンボル以外にも、人間によって発明された他の多くのシンボルがあります。そして、それらをエンコードするには32ビットが必要なほどたくさんあります。

Golangでは、stringbytesのシーケンスです。ただし、複数のバイトがルーンのコードポイントを表すことができるため、文字列値にルーンを含めることもできます。そのため、[]runeに、またはその逆に変換できます。

Unicodeパッケージ http://golang.org/pkg/unicode/ は、チャレンジの豊かさを味わうことができます。

40
fabrizioM

FabrizioMの answer にコメントを投稿するのに十分な評判がないので、代わりにここに投稿する必要があります。

ファブリツィオの答えはおおむね正解であり、彼は確かに問題の本質を捉えました。

文字列は、ではなくであり、必ずしもルーン文字のシーケンスです。これは「バイトのスライス」のラッパーであり、sliceはGo配列のラッパーです。これはどのような違いをもたらしますか?

rune型は必然的に32ビット値です。つまり、ルーン型の値のシーケンスは、必ずいくつかのビットx * 32を持つことになります。代わりに、バイトシーケンスである文字列の長さはx * 8ビットです。すべての文字列が実際にUnicodeである場合、この違いは影響しません。ただし、文字列はバイトのスライスであるため、GoはASCIIまたはその他の任意のバイトエンコーディングを使用できます。

ただし、文字列リテラルは、UTF-8でエンコードされたソースに書き込む必要があります。

情報源: http://blog.golang.org/strings

22
Strangework

素人がruneを理解できるように、言語をシンプルにしようとしました。

ルーンはキャラクターです。それだけです。

これは単一の文字です。世界中のあらゆる言語のアルファベットの文字です。

文字列を取得するには

double-quotes ""

OR

back-ticks ``

文字列はルーンとは異なります。ルーン文字では

single-quotes ''

今、ルーンはint32... Uhのエイリアスでもありますか?

Runeがint32のエイリアスである理由は、以下のようなコーディングスキームで enter image description here

各文字はいくつかの数字にマッピングされるため、保存されている数字です。たとえば、a97にマッピングされ、その番号を格納するときは単なる番号であるため、ルーンはint32。 しかし、単なる数字ではありません。 32個の「ゼロと1」または「4」バイトの数字です(注:UTF-8は4バイトのエンコード方式です)

ルーン文字と文字列の関係は?

文字列はルーン文字のコレクションです。次のコードでは:

    package main

    import (
        "fmt"
    )

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

文字列をバイトのストリームに変換しようとします。出力は次のとおりです。

[72 101 108 108 111]

その文字列を構成する各バイトがルーン文字であることがわかります。

18
Suhail Gupta

(上記の答えはまだstring[]runeの違いと関係を非常に明確に述べていないという感覚を得たので、例を使って別の答えを追加しようと思います。)

@Strangeworkの答えが言ったように、string[]runeは静かに異なっています。

違い-string[]rune

  • string valueは読み取り専用のバイトスライスです。また、文字列リテラルはutf-8でエンコードされます。 stringの各文字は実際に1〜バイトを取りますが、各rune4バイトを取ります
  • stringの場合、len()とindexは両方ともバイトに基づいています。
  • []runeの場合、len()とindexは両方ともルーン(またはint32)に基づいています。

関係-string[]rune

  • stringから[]runeに変換すると、その文字列の各utf-8文字はruneになります。
  • 同様に、逆変換では、[]runeからstringに変換すると、各runestringのutf-8文字になります。

ヒント:

  • 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你好の長さは11です。これは、最初の5文字はそれぞれ1バイトのみを使用し、最後の2文字は3バイトを使用するためです。

    • したがって、total bytes = 5 * 1 + 2 * 3 = 11
    • 文字列のlen()はバイトに基づいているため、最初の行はlen: 11を出力します
    • 文字列のインデックスもバイトに基づいているため、次の2行はuint8型の値を出力します(goのbyteuint8のエイリアス型であるため)。
  • string[]runeに変換すると、7個のutf8文字、つまり7個のルーン文字が見つかりました。

    • []runelen()はルーンに基づいているため、最後の行はlen: 7を出力します。
    • インデックスを介して[]runeを操作すると、ルーンに基づいてアクセスします。
      各ルーンは元の文字列のutf8文字に由来するため、len()[]runeのインデックス操作の両方がutf8文字に基づいていると言うこともできます。
9
Eric Wang

他の誰もがルーンに関する部分をカバーしているので、私はそれについて話すつもりはありません。

ただし、引数がない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")
}

もっと読むことができます こちら

7
Shashank Goyal

ルーンはint32値であるため、Unicodeコードポイントを表すために使用されるGo型です。 Unicodeコードポイントまたはコード位置は、単一のUnicode文字を表すために通常使用される数値です。

0
Remario