Go

Goのslice expressionについて

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
      • ということは、もし対象の要素数が未知数なら、あらかじめサイズの確認は必須
  • 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

参考文献

https://medium.com/golangspec/slice-expressions-in-go-963368c20765