-Go- Unicode? UTF-8? byte型, rune型とは
Unicodeとは
人間界の文字列をコンピュータが理解できるように16進数で表してマッピングしたもの。
一文字ずつ16進数の値が対応しており、その値はcode point(文字集合の中での位置を表しているからpoint)と呼ばれている。例えば、AだとU+0041と表される。
UTF-8とは
Goはcodepointを表す符号化方式としてUTF-8を採用している。符号化方式とはUnicodeのcode pointをコンピュータが扱うデータ形式(バイト列)に置き換えるための規則のこと。符号化方式によってcode pointを何byteで扱うのかが異なる。
UnicodeをUTF-8で符号化する方法については以下の記事が分かりやすい。
UTF-8の符号化方法について UTF-8の符号化方法
例えば、Unicode U+3042 の「あ」をUTF-8に変換するにはこのように行う。
https://gyazo.com/7615d752e93b24e1372418a43adb489f
ちなみに、UTF-8, UTF-16, UTF-32 はUnicodeのcode pointを8bit単位, 16bit単位, 32bit単位で符号化した符号化方式のことです。
UnicodeとUTF-8・UTF-16・UTF-32の違いとは
byte型とは
Goでstringにインデックスでアクセスするとbyte型(unit8)が返ってくる。
例えば、「あ」はUTF-8ではE3 81 82であり、インデックスにアクセスすると以下のようになる。(当たり前だけど16進数は2文字で1byte)
code: Go
s := "あ"
fmt.Printf("%x", s0) // e3
fmt.Printf("%x", s1) // 81
fmt.Printf("%x", s2) // 82
fmt.Printf("%x", []byte(s)) // e38182
// %x は16進数での表現を意味する
rune型とは
文字をbyte型の配列で表すことができたけど、文字によって何バイトで表されるのかが変わってしまい厄介。例えば、アルファベットは2byte, ひらがなは3byte, 絵文字は4byteとbyte配列の長さが変わってしまう。
そこでGoではUnicodeのcode pointをそのままバイト文字列として扱える(表すことができる)int32型(rune型)を用意している。(疑問点: rune型はUTF-32と同じ値になるってこと?)
→ rune型はUnicodeコードポイントを表す特殊な整数型のこと。
例として、UnicodeU+3042で表される「あ」はrune型で同じ値で表されていることが分かる。
code: Go
s := "あ"
fmt.Printf("%x", []rune(s)) // 3042
fmt.Printf("%x", 'あ') // 3042
また、Goではシングルクウォートで文字を囲うことでrune型を表現することができる。
これで何となく文字列(string型)をrangeで回した時に値がrune型となるのかが分かった。
code: Go
for _, v := range "すぎた" {
// v はrune型として取り出される。
}
rune型であれば確実に一文字ずつ(4byte単位で大きく。大は小を兼ねる作戦か。)取り出せるわけだ。文字列を扱いたい時はrune型(int32)単位で取れると便利だっていうことか。byteだったら「す」だけで3つも値があるからおかしい。もし文字列を1byte単位で回してたら何回回してんねん!ってツッコミたくなるはずだ。
あと文字にindexでアクセスする時にbyte文字列が取れる理由も何となく分かった。
code: GO
fmt.Printf("%x", "あ"0) //e3
文字はbyte配列で構成されているからだ。あたり前だけど。
感想&分からないこと
jiroshin.icon 調べてみて大体わかったけど、U+3042 がint32型でも3042となる計算方法(UTF-32の符号化方法と一緒? UTF-32の符号化方法も分からないのだけど。)が良く分からない。(単純にUnicodeは16進数だから32bitあればそのまま同じ値を使える?)
あと、%vで取れるこの値↓ は何者? 分からない。→ これは16進数を10進数で表したものだった!つまり上はUnicodeコードポイントを10進数で表したもの。下は1byteを10進数で表したもの。
code: Go
fmt.Printf("%v" , []rune("あ")) // 12354
fmt.Printf("%v" , []byte("あ")) // 227 129 130
jiroshin.icon 完全に理解した:)
参考:
Goのruneを理解するためのUnicode知識
文字コードUTF-8とは? 仕組みとコード表
UTF-8の符号化方法について UTF-8の符号化方法
Unicode, UCS-2/4, UTF-8/16/32についての整理
Goメモ-37 (stringとruneとbyteの変換)
#Golang