2014年12月31日水曜日

Goのスライス(slice)を復習

年末年始で落ち着いて時間をとれたので、Goのスライス(slice)について復習しました。以下、参照させて頂いた記事の一覧です。黒四角(■)が付いている記事を中心に読み進めました。

Go Slices関連

Go言語のスライスを理解しよう(オリジナルを踏まえたスライド)
 □Go言語のArrayとSliceについて(オリジナルを要約した記事)
 □slices_usage_and_internals.md(オリジナルを日本語訳した記事)
 □Go Slices: usage and internals(オリジナルの記事)

Jxckさんの記事
 □SliceTricks
 □Arrays, slices (and strings): The mechanics of 'append'
Go のスライスでハマッたところ(その2)
 □GoのSliceもヤバイ

自分として復習できた点は、以下の通りです。

・配列から要素を取得する時にインデックスを指定するが、上限値は取得したいインデックスの+1である。

ド忘れしていました(^^;) ["a", "b", "c", "d", "e"] という配列から ["b", "c", "d"] を取得する場合のインデックス指定は [1:3] ではなく [1:4] です。Pythonのスライス操作と同じでしたね。

・スライスに値を追加する時は、キャパシティを超えるか超えないかを意識する。

再確認しておきたかった点です。値を追加してキャパシティを超える場合、内部ではメモリが再確保(アロケート)されたりスライスが新規作成されたりとコスト高になっています。Goにはガベージコレクションがあるとは言えど、メモリ効率なども意識できるようになれば初心者を卒業です。

・スライスの実体はSliceHeader構造体である。

新しく知り得たことです。関数の引数にスライスを指定するとコピーされます。関数内で引数のスライスのLenやCapを変化させてもこれらは値なので、その結果は関数に引き渡す前のスライスには反映されません。Dataは参照元の配列へのポインタでなので、関数内で配列を変化させた場合はどちらのスライスからも反映された状態を取得できます。