
結論
- runeはGoにおける型の1種類
- rune型を用いることで、文字列を1文字づつ扱うことができる
前提知識
まず最初に文字コード(コードポインタ)や文字集合と符号化方式について理解しましょう。
こちらの記事にまとめておきました。
Golangにおける文字の扱い
この記事で詳しく書かれていますが、以下のようなコードを実行すると227 129 130が出力されます。
s := "あ"
for i := 0; i < len(s); i++ {
b := s[i] // byte
fmt.Println(b)
}
出力:
227
129
130
直感で考えたり、他の言語だったりするとあと表示されるので違和感があると思います。
GoではString型に対してSliceでアクセスを行うと、その文字が格納されているByte値を出力します。
s := "あ"
for i := 0; i < len(s); i++ {
b := s[i] // byte
fmt.Printf("%x\n", b)
}
出力:
e3
81
82
このように%xをつけて16進数で表示するようにすると、UTF-8で表現されたあという文字が出力されることがわかりやすいと思います。
つまりまとめると、あいうえおみたいな文字列を1文字ごとにループで回すような処理をするときにSliceでIndexアクセスをさせると予想に反してバイト値へのアクセスになってしまうということです。
runeについて
これを回避するために使えるのがrune型です。rangeをつかってループを回すことで変数rにはrune型の値が入ります。
s = "あいうえお"
for _, r := range s {
// rune
fmt.Println(r)
}
出力:
12354
12356
12358
12360
12362
しかしrune型は対象の文字列のコードポイントを表示するものになるので、「あ」とか「い」が表示されるわけではなくその文字に割り当てられている数字が表示されます。
ややこしいことに、このとき表示される数字は「Unicodeの番号を10進数に変換したもの」です。例えば「あ」のUnicode番号は「U+3042」で、これを10進数表記に変更すると「12354」になります。
rune型の数字を元の文字に戻すにはstring()を使ってあげましょう。
するとこのように出力することができます。
fmt.Println("---")
for _, r := range s {
// rune
fmt.Println(string(r))
}
出力:
あ
い
う
え
お
ということでここまでがrune型の説明でした!