Edited at

Goのフルスライス式 a[x:y:z] は何のためにある?

More than 5 years have passed since last update.

Goのフルスライス式を使うと、スライシングするときにキャパシティを指定することができる。

普通のスライス式ではスライスした範囲を超えて配列の値にアクセスしたり変更することができる。

a := make([]int, 100) // 長さ100の配列

s := a[0:10] // 長さ10のスライスsを切り出す
t := s[0:100] // sからsより長いスライスtを切り出す

上のようにすると、短いスライスから長いスライスを切り出して、元の配列の本来触れてほしくなかったところもアクセスできてしまう。組み込み関数のappendはキャパシティがある限り元の配列を上書きすることになっているので、appendとサブスライスを使っていると知らない間にオーバーランしてしまっていることもありえる。

フルスライス式を使うとそのようなことを防止できる。

a := make([]int, 100) // 長さ100の配列

s := a[0:10:10] // 長さ10のスライスsを切り出す
t := s[0:100] // ランタイムエラーになる

でもこの式って必要? というと、ほとんど使う機会はない。配列は通常1つの目的のために別々にアロケートされるので、無関係なものがオーバーランして困るということがほとんどないからだ。

積極的にフルスライス式を使いたいケースは、大きな配列を確保して小さくそれを切り出して使うような、ある種のメモリアロケータを自前で書くときのようなケースだ。そういう機会はほとんどないと思うけど、文法上存在する機能なので覚えておいたほうが「これはなんだ?」とあとで思わなくて済む。でもまあその程度だ。