概要
よく忘れるので、自分用にメモです。
Goの文字列は、 string
型で表現されます。
string
は、文字列をバイト列で持っています。
なので、string
に対して、len()
するとバイト数が取得できます。
Goの文字は rune
型で表現されます。
rune
は、文字をUnicodeコードポイントで持っています。
なので、[]rune
に対して len()
すると文字数が取得できます。
string
と[]rune
と[]byte
は相互に変換可能です。
[]byte
にstring
を与える事によって、その文字列のバイト列になるstring
に[]byte
を与える事によって、バイト列の文字列となる[]rune
にstring
を与える事によって、その文字列のrune列となるstring
に[]rune
を与える事によって、そのrune列の文字列となる
上を見ると、string
が中継地点となっていて rune
と byte
を変換する場合は
一旦 string
にしてから、望む方向へ変換してやればいいことがわかります。
補足として、途中のstring変換をせずに直接 rune と byte を変換するには utf8.EncodeRune()
などを利用すればできます。
こういうのは、実際のコード見たほうが早いと思いますので、以下にサンプルです。
サンプル
package string_ import ( "fmt" "unicode/utf8" ) // StringRuneByteConvert は、文字列とルーンとバイト列の変換のサンプルです. func StringRuneByteConvert() error { // ----------------------------------------------------- // Goでの文字列は string 型で表現される。 // string は、文字列をバイト列で表現しているもの。 // なので、string に対して len() とするとバイト数が取得できる // (Goの文字列表現はUTF-8) // // Goでの文字は rune 型で表現される。 // rune は、文字をUnicodeコードポイントで表現しているもの。 // なので、 []rune に対して len() とすると文字数が取得できる。 // // string/[]rune/[]byte は相互に変換可能。 // // []byte に string を与える事によって、その文字列のバイト列になる // string に []byte を与える事によって、バイト列の文字列となる // []rune に string を与える事によって、その文字列のrune列となる // string に []rune を与える事によって、そのrune列の文字列となる // // 上を見る通り、stirng が中継地点となっていて // rune と byte を変換する場合は、一旦 string にしてから // 望む方向へ変換する。 // // utf8.EncodeRune() を利用することで中間生成のstringを省く事もできる. // // REFERENCES:: // - https://stackoverflow.com/questions/29255746/how-encode-rune-into-byte-using-utf8-in-golang // - https://qiita.com/masakielastic/items/01a4fb691c572dd71a19 // - https://golang.org/ref/spec#Conversions_to_and_from_a_string_type // ----------------------------------------------------- s := "こんにちわworld" // そのまま len(s) とすると、バイト数となる fmt.Printf("len(s) == %d\n", len(s)) // runeに変換 r := []rune(s) fmt.Printf("len(r) == %d\n", len(r)) // runeはUnicodeコードポイントを示しているので日本語などでは // 一つのruneがNバイトとなる. for i, v := range r { // runeをバイト列に変換 // 一旦、runeを文字列にして、そこからバイト列に変換する b := []byte(string(v)) fmt.Printf("rune[%d] %d byte(s)\n", i, len(b)) } // ---------------------------------------------------------- // runeのスライスを string を経由せずに、直接 byte スライスに変換 // (https://stackoverflow.com/questions/29255746/how-encode-rune-into-byte-using-utf8-in-golang) // ---------------------------------------------------------- // 予めUtf-8の1文字での最大バイト数分で大きめにバッファを用意しておく buf := make([]byte, len(r)*utf8.UTFMax) // rune を一つずつエンコード count := 0 for _, v := range r { count += utf8.EncodeRune(buf[count:], v) } // スライスのサイズを調整 buf = buf[:count] fmt.Printf("%s(%v)\n", buf, buf) return nil }
https://github.com/devlights/try-golang/blob/master/basic/string_/string_rune_byte_convert.go
実行結果は以下のような感じ。
[Name] "string_rune_byte_convert" len(s) == 20 len(r) == 10 rune[0] 3 bytes rune[1] 3 bytes rune[2] 3 bytes rune[3] 3 bytes rune[4] 3 bytes rune[5] 1 bytes rune[6] 1 bytes rune[7] 1 bytes rune[8] 1 bytes rune[9] 1 bytes こんにちわworld([227 129 147 227 130 147 227 129 171 227 129 161 227 130 143 119 111 114 108 100])
参考情報
サンプル書いた後で、上のQiitaの記事を見つけたのですが、こちらの方が100倍詳しく、かつ、わかりやすく書かれていました。
過去の記事については、以下のページからご参照下さい。
- いろいろ備忘録日記まとめ
サンプルコードは、以下の場所で公開しています。
- いろいろ備忘録日記サンプルソース置き場