string とは
Strings behave like slices of bytes but are immutable: once created, it is impossible to change the contents of a string.
The Go Programming Language Specification - String types より。
訳すと、
文字列は byte スライスのような振る舞いを持つ。 ただし、1度作成したら変更は不可。
要するに string は、
- 読み取り操作は byte スライスのように利用できる。
- 結合などの操作をする度に新しい string を作成するので、こうした操作には向かない。
ということ。
よって、文字列を操作する際のルールとしては、
- 文字列の生成・変更などする間は、[]byte 型で操作する
- できあがったものを string にする
を守ったほうが、メモリや演算コストを抑えられる。
string を +
オペレータでジャンジャン結合できちゃうのは、便利だけどマズい。
これは、Go言語で文字列の結合時間を計測してみたで計測した通り。
string の文字コード
Go言語はソースを UTF-8 として解釈するため、文字列定数の値も UTF-8 で扱われている。 また、多くの文字列を扱うライブラリも UTF-8 用に作成されている。 UTF-8 の特徴として、
文字列の検索を単なるバイト列の検索として行っても、文字境界と異なる個所でマッチしてしまうことがない。
Wikipedia UTF-8より。
があるので、極力 byte 操作を行うことができる。
string 自体は byte スライスのようなものなので、文字コードには依存せず UTF-8 以外の文字コードの文字列も格納できる。 文字コードの変換については、Version 1.0.3 標準ライブラリにはないので、外部ライブラリを利用する必要がある。
以下、自分なりのルールを書いてみる。
文字単位で文字列を操作する
x := []byte(s)
で型を []byte に変換する。- スライス操作でデータを操作する。
return string(x)
で string に変換し直す。
文字列の結合
文字列を1回だけ結合する
string を +
オペレータで結合する。
複数回、文字列を結合する
bytes.Buffer
を利用する。
- 結果文字列の最大バイト数が想定できないなら、単に
new(bytes.Buffer)
として利用する。 - 結果文字列の最大バイト数が想定できているなら、
make([]byte, 0, size)
で容量を指定してバッファを作成すると、バッファの拡張が発生しないため、効率が良い。 - 結果文字列の最大バイト数が64bytes以下なら、bytes.Buffer 内の一時領域を使用するため、
make([]byte, 0, size)
は不要。単にnew(bytes.Buffer)
でよい。
bytes.Buffer に Rune を追加する
マルチバイトの 1 文字定数を追加する場合、Rune 定数よりも文字列定数として追加したほうがバイト変換が発生しない分、コストが低い。
fmt.Printf()系で文字列を作成する
1回だけの操作
fmt.Sprintf()
を使用する。
bytes.Buffer と共に使用する
fmt.Fprintf()
はio.Writer
へ結果を出力するので、出力先に bytes.Buffer を与えると結果を Buffer に書き出せる。
0 件のコメント:
コメントを投稿