- 配列の部分列にアクセスするための軽量データ構造
- sliceはアクセス手段なので、複数のsliceは一つの配列を共有することができる
- sliceの背後にある配列を基本配列と呼ぶ
図4.1をみるとわかりやすいので参照。
- pointer
- sliceが指している最初の要素
- length
- len関数で取得
- sliceの要素数.capacityは超えられない
- capacity
- cap関数で取得
- sliceの最初の要素から配列末尾までの長さ
- []T
- 長さのない配列のように見える。
s[i:j]// 0 <= i <= j <= cap(s)
s[i:i+1]//iの値を取得できる
s[i:] //i以降すべて
s[cap(s)+1] // panic!
- sliceは可変長の連続した要素で、すべての要素の型が同じ。
- stringをsliceしたら型はstring、[]byteなら[]byteになる。
- sliceリテラルは暗黙的に正しいサイズの型で配列と、ポインタを生成する。
- 値は順番に並ぶ
- indexでアクセス
- ==でスライスの先にある要素値が全て同じであるか比較できない
- スライス同士はポインタ比較になる(shallow test)
- bytes.Equalを使えば[]byte型だけは比較可能
- 無限ループになる
- sliceの要素は参照型かつ、slice自身を含んだsliceを作れる
- http://stackoverflow.com/questions/36077566/how-can-a-slice-contain-itself
- 参照先の基本配列の要素値がdeep testの最中に変更されるかもしれない
- それゆえmapのkeyにsliceを使うのは適していない。
- http://golang.jp/go_faq#map_keys
- sliceについては==を一切使わない
- arrayとsliceの==の挙動の違いを理解して使うのは紛らわしい
- 例外として、nilとの比較に==を使う
- sliceのzero valueがnilのとき、基本配列をもっていない
- nil sliceはlenもcapも0だが、non-nil sliceの場合([]int{})も0
- どのような型もnil値を持てる。特定のslice typeのnil値は[]int(nil)のような変換式を使って書くことができる
- nil sliceにおいてnil以外との比較は、zero lengthのsliceと同じ振る舞いをする。
- len(s) == 0 または s == nil
- makeは空のsliceを作る。
- capを指定しない場合はlenと同じ値になる。
- makeは裏で匿名配列を作成し、sliceを返す。
- 匿名配列にアクセスできるのは、そのsliceのみ(?)
make([]T, len) //(lenとcapが同じなので)配列全体をみている
make([]T,len,cap) // len~capまでの長さの基本配列しか生成しない
- appendはsliceを理解するうえで重要
- appendはcapを超えないなら、同じ基本配列を指すsliceを作るが、capを超えると、新規に基本配列を作成して、そのsliceを返す
- 元のsliceが参照していた配列とは別物になる。
余談: []rune("hoge"); で一文字ずつ分解できるのでappendとloopを組み合わせる必要はない。
- copy(dest,src) // dest = srcのイメージらしい
- slice間のcopyができる
- 戻り値はcopyした要素の数。
- copyのdest,srcは同じsliceであることもある。
- copy(s[1:2],s[4:5])
- copy元のほうが長さが長くても安全
s := []int{1,2,3,4,5}
s2 := []int{10,9,8,7,6,5,4,3,2,1}
num := copy(s[0:2],s2[0:10]) //s2[0:10]の先頭二文字しかcopyされない.
- overlapでも安全
num := copy(s[2:3],s);
fmt.Println(s); //[1 2 1 4 5]
fmt.Println(num); //1
appendで新規に作られる基本配列のサイズはappendのたびにreallocatonしなくていいように ある程度大きめのサイズを確保してくれる。
配列はdirect、sliceはpointer
- ? to update them requires an assignment like the one above. この点において、pureな参照型ではないが、しかしstructのような集合型と共有点がある。
type InSlice struct {
ptr *int
len, cap int
}
- rotate,reverse,nonemptyを実装してみよう。
- sliceはstackを実装するのに使われる。