Goのrune
とは何ですか?
私はグーグルをしてきましたが、Golangは1行でしか言いません:rune
はint32
のエイリアスです。
しかし、スワッピングのように整数が使用されるのはなぜですか?
以下は関数スワップケースです。すべての<=
と-
とは何ですか?
そして、なぜ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)
}
私は、これがrune
をstring
にマッピングし、交換された文字列を返すことができることを理解しています。しかし、ここでrune
またはbyte
が正確にどのように機能するかはわかりません。
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'
が得られ、その逆も同様です。
Go langリリースノートから: http://golang.org/doc/go1#rune
ルーンはタイプです。 32ビットを占有し、 nicodeCodePoint を表すことを意図しています。類推として、「ASCII」でエンコードされた英語の文字セットには128個のコードポイントがあります。したがって、バイト(8ビット)内に収めることができます。この(誤った)仮定から、Cは文字を「バイト」char
として扱い、「文字列」を「文字のシーケンス」char*
として扱いました。
しかし、何を推測します。 「abcde ..」シンボル以外にも、人間によって発明された他の多くのシンボルがあります。そして、それらをエンコードするには32ビットが必要なほどたくさんあります。
Golangでは、string
はbytes
のシーケンスです。ただし、複数のバイトがルーンのコードポイントを表すことができるため、文字列値にルーンを含めることもできます。そのため、[]rune
に、またはその逆に変換できます。
Unicodeパッケージ http://golang.org/pkg/unicode/ は、チャレンジの豊かさを味わうことができます。
FabrizioMの answer にコメントを投稿するのに十分な評判がないので、代わりにここに投稿する必要があります。
ファブリツィオの答えはおおむね正解であり、彼は確かに問題の本質を捉えました。
文字列は、ではなくであり、必ずしもルーン文字のシーケンスです。これは「バイトのスライス」のラッパーであり、sliceはGo配列のラッパーです。これはどのような違いをもたらしますか?
rune型は必然的に32ビット値です。つまり、ルーン型の値のシーケンスは、必ずいくつかのビットx * 32を持つことになります。代わりに、バイトシーケンスである文字列の長さはx * 8ビットです。すべての文字列が実際にUnicodeである場合、この違いは影響しません。ただし、文字列はバイトのスライスであるため、GoはASCIIまたはその他の任意のバイトエンコーディングを使用できます。
ただし、文字列リテラルは、UTF-8でエンコードされたソースに書き込む必要があります。
素人がrune
を理解できるように、言語をシンプルにしようとしました。
ルーンはキャラクターです。それだけです。
これは単一の文字です。世界中のあらゆる言語のアルファベットの文字です。
文字列を取得するには
double-quotes ""
OR
back-ticks ``
文字列はルーンとは異なります。ルーン文字では
single-quotes ''
今、ルーンはint32
... Uhのエイリアスでもありますか?
Runeがint32
のエイリアスである理由は、以下のようなコーディングスキームで
各文字はいくつかの数字にマッピングされるため、保存されている数字です。たとえば、aは97にマッピングされ、その番号を格納するときは単なる番号であるため、ルーンはint32。 しかし、単なる数字ではありません。 32個の「ゼロと1」または「4」バイトの数字です(注:UTF-8は4バイトのエンコード方式です)
ルーン文字と文字列の関係は?
文字列はルーン文字のコレクションです。次のコードでは:
package main
import (
"fmt"
)
func main() {
fmt.Println([]byte("Hello"))
}
文字列をバイトのストリームに変換しようとします。出力は次のとおりです。
[72 101 108 108 111]
その文字列を構成する各バイトがルーン文字であることがわかります。
(上記の答えはまだstring
と[]rune
の違いと関係を非常に明確に述べていないという感覚を得たので、例を使って別の答えを追加しようと思います。)
@Strangework
の答えが言ったように、string
と[]rune
は静かに異なっています。
違い-string
&[]rune
:
string value
は読み取り専用のバイトスライスです。また、文字列リテラルはutf-8でエンコードされます。 string
の各文字は実際に1〜バイトを取りますが、各rune
は4バイトを取りますstring
の場合、len()
とindexは両方ともバイトに基づいています。[]rune
の場合、len()
とindexは両方ともルーン(またはint32)に基づいています。関係-string
&[]rune
:
string
から[]rune
に変換すると、その文字列の各utf-8文字はrune
になります。[]rune
からstring
に変換すると、各rune
はstring
の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
を出力しますuint8
型の値を出力します(goのbyte
はuint8
のエイリアス型であるため)。string
を[]rune
に変換すると、7個のutf8文字、つまり7個のルーン文字が見つかりました。
[]rune
のlen()
はルーンに基づいているため、最後の行はlen: 7
を出力します。[]rune
を操作すると、ルーンに基づいてアクセスします。len()
と[]rune
のインデックス操作の両方がutf8文字に基づいていると言うこともできます。他の誰もがルーンに関する部分をカバーしているので、私はそれについて話すつもりはありません。
ただし、引数がない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")
}
もっと読むことができます こちら 。
ルーンはint32値であるため、Unicodeコードポイントを表すために使用されるGo型です。 Unicodeコードポイントまたはコード位置は、単一のUnicode文字を表すために通常使用される数値です。