Goのslice expression(スライス式, スライシング)をちゃんと理解できてなかったので、反省を込めてメモ。
まず何の変哲もないスライス。
sli := []int{1, 2, 3, 4, 5}
スライスの添字は 0
から始まり、 要素数-1
までになる。このsliの場合、添字は0 ~ 4となる。
slice expressionは、配列や配列へのポインタやスライスから、別のスライスを作るときに使う記法のこと。(ちなみに文字列にも使えるが、結果は文字列になる点が少し違う)
https://golang.org/ref/spec#Slice_expressions
s2 := sli[0:5] // 1, 2, 3, 4, 5
こんな風に a[low : high]
と書くことで別のスライスを切り出すことができる。
- lowとhighはどちらも添字が基準で、 $low \leq i < high$ の範囲が切り取られる
-
sli[0:5]
とは、 $0 \leq i < 5$ の範囲を抜き出すので、つまりは 添字0~4を抜き出す意味になる -
sli[:3]
のようにlowを省略すると0
の意味になる。 $0 \leq i < 3$ と同じ。 -
sli[1:]
のようにhighを省略するとlen(sli)
の意味になる。この場合は $1 \leq i < 5$ と同じ- つまり、
sli[:]
はsli[0:len(sli)]
と同じ意味
- つまり、
slice expressionの性質
- できあがる新sliceの要素数は、
high - low
- low == highな値を設定すると、空のsliceが返ってくる
- $0 \leq low \leq high \leq len(a)$ を満たさないと駄目。lowとhighの大小関係も重要
- 満たしてないとpanic
- ということは、もし対象の要素数が未知数なら、あらかじめサイズの確認は必須
- 満たしてないとpanic
- pythonなど、他言語にあるような超高機能なslice式ではない
- 負の値を指定してお尻から切り出す〜みたいな機能はない
- len()を使え、ってことかな?
- ステップを指定したりreverseを作る機能もない
- そういうのはライブラリを使うのがgo文化ですね
- 負の値を指定してお尻から切り出す〜みたいな機能はない
なんでhighは一個大きな数字にしてるんだろう?
たぶん色々なロジックを書くときにわざわざ-1をせずに済み、便利だからでしょう。
配列の添字が1始まりじゃなくて0始まりになってるのと同じ理由だと思う。
full slice expressionについて
使ったことがないです。使いみちがよくわからない…
capをあえて広げて切り取れるという構文がある。
numbers := [10]int{0,1,2,3,4,5,6,7,8,9}
s := numbers[2:4:6]
fmt.Println(s) // [2, 3]
fmt.Println(cap(s)) // 4
参考文献