Skip to content

Instantly share code, notes, and snippets.

@tokubass
Created June 8, 2016 09:58
Show Gist options
  • Save tokubass/49f3e0caa488a4aedd638192fc38ce55 to your computer and use it in GitHub Desktop.
Save tokubass/49f3e0caa488a4aedd638192fc38ce55 to your computer and use it in GitHub Desktop.
The Go Programming Language - ch4 slice

4.2 Slices

  • 配列の部分列にアクセスするための軽量データ構造
  • sliceはアクセス手段なので、複数のsliceは一つの配列を共有することができる
  • sliceの背後にある配列を基本配列と呼ぶ

3つのコンポーネント

図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と配列の違い

共通点

  • sliceリテラルは暗黙的に正しいサイズの型で配列と、ポインタを生成する。
  • 値は順番に並ぶ
  • indexでアクセス

相違点

  • ==でスライスの先にある要素値が全て同じであるか比較できない
  • スライス同士はポインタ比較になる(shallow test)
  • bytes.Equalを使えば[]byte型だけは比較可能

比較

deep testは避ける

ベストプラクティス

  • sliceについては==を一切使わない
    • arrayとsliceの==の挙動の違いを理解して使うのは紛らわしい
    • 例外として、nilとの比較に==を使う

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

  • makeは空のsliceを作る。
  • capを指定しない場合はlenと同じ値になる。
  • makeは裏で匿名配列を作成し、sliceを返す。
    • 匿名配列にアクセスできるのは、そのsliceのみ(?)
make([]T, len)    //(lenとcapが同じなので)配列全体をみている
make([]T,len,cap) // len~capまでの長さの基本配列しか生成しない

4.2.1 The append Function

append関数

  • appendはsliceを理解するうえで重要
  • appendはcapを超えないなら、同じ基本配列を指すsliceを作るが、capを超えると、新規に基本配列を作成して、そのsliceを返す
  • 元のsliceが参照していた配列とは別物になる。

余談: []rune("hoge"); で一文字ずつ分解できるのでappendとloopを組み合わせる必要はない。

copy関数

  • 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しなくていいように ある程度大きめのサイズを確保してくれる。

sliceの要点

配列はdirect、sliceはpointer

  • ? to update them requires an assignment like the one above. この点において、pureな参照型ではないが、しかしstructのような集合型と共有点がある。
type InSlice struct {
     ptr *int
     len, cap int
}

4.2.2 In-Place Slice Techniques

  • rotate,reverse,nonemptyを実装してみよう。
  • sliceはstackを実装するのに使われる。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment