go言語のsliceの基本的な動きを見てみる

##slice
基本操作については[こちら](http://qiita.com/egnr-in-6matroom/items/282aa2fd117aab9469bd)にまとめました。

固定サイズの配列では、サイズがいっぱいになった場合に、サイズの大きい配列を作って写しかえるなど、メモリの再確保が必要になる。したがって、予め大きなサイズで配列を確保することがあるが、使っていない部分へアクセスしないために工夫が必要になる。
goでは予めメモリに十分確保した配列の一部を、スライスとして定義できる。

おなじメモリから切出したスライスは、当然同じメモリを操作するので、ポインタには十分注意する必要がある。

```go:slice_test1.go
package main

import (
	"fmt"
)

func main() {
	arr := make([]int, 10)
	for i := 0; i < 10; i++ {
		arr[i] = i
	}
	//
	fmt.Printf("len\tcap\tpointer\n")
	fmt.Printf("%d\t%d\t%p\n", len(arr), cap(arr), arr)
	
	// 切り取ってもメモリ上の容量はおなじ
	slice := arr[:5]

	fmt.Printf("%d\t%d\t%p\n", len(slice), cap(slice), slice)
	fmt.Printf("%v\n", arr)
	fmt.Printf("%v\n\n", slice)
	// 同じメモリを操作するので、sliceでappendすると、元のarrも変化する
	slice = append(slice, 10)
	fmt.Printf("%v\n", arr)
	fmt.Printf("%v\n\n", slice)
}
// 実行結果
// len     cap     pointer
// 10      10      0xc08200a280
// 5       10      0xc08200a280
// [0 1 2 3 4 5 6 7 8 9]
// [0 1 2 3 4]
//
// [0 1 2 3 4 10 6 7 8 9]
// [0 1 2 3 4 10]
```
##copy
sliceはポインタが代入される参照渡しとして扱われる。
値渡しするときは、copy関数を使用する。

```go:slice_test2.go
package main

import (
	"fmt"
)

func main() {
	arr := make([]int, 10)
	for i := 0; i < 10; i++ {
		arr[i] = i
	}
	//
	fmt.Printf("len\tcap\tpointer\n")
	fmt.Printf("%d\t%d\t%p\n", len(arr), cap(arr), arr)

	// 新しいスライスへコピーする
	slice := make([]int, 5)
	copy(slice, arr[:5])

	fmt.Printf("%d\t%d\t%p\n", len(slice), cap(slice), slice)
	fmt.Printf("%v\n", arr)
	fmt.Printf("%v\n\n", slice)
	// 別のメモリを操作するので、sliceでappendすると、元のarrは変化しない
	slice = append(slice, 10)
	fmt.Printf("%v\n", arr)
	fmt.Printf("%v\n\n", slice)
// 実行結果
// len     cap     pointer
// 10      10      0xc08200a280
// 5       5       0xc082005e00
// [0 1 2 3 4 5 6 7 8 9]
// [0 1 2 3 4]

// [0 1 2 3 4 5 6 7 8 9]
// [0 1 2 3 4 10]
}

```

##append
`append`でsliceに要素追加するとき、sliceの挙動がよく分かる。
例として、capacityが2のスライスに要素を追加していく場合の変化を見てみる。
自動で現在のキャパシティと同じ容量が追加（つまり倍）され、そのタイミングでポインタも変化している（メモリが再確保されている）ことがわかる。

```go:slice_test3.go
package main

import (
	"fmt"
)

func main() {
	capacity := 2
	b := make([]string, 0, capacity)

	fmt.Printf("idx\tsize\tpointer\t\tarray \n")
	for i:=0; i < 20; i++ {
		b = append(b, "X")
		fmt.Printf("%d\t%d\t%p\t%v\n", i, len(b), b, b)
	}
}

// 実行結果
// idx     len     cap     pointer         array
// 0       1       2       0xc082006560    [X]
// 1       2       2       0xc082006560    [X X]
// 2       3       4       0xc0820082c0    [X X X]
// 3       4       4       0xc0820082c0    [X X X X]
// 4       5       8       0xc08204a000    [X X X X X]
// 5       6       8       0xc08204a000    [X X X X X X]
// 6       7       8       0xc08204a000    [X X X X X X X]
// 7       8       8       0xc08204a000    [X X X X X X X X]
// 8       9       16      0xc08204c000    [X X X X X X X X X]
// 9       10      16      0xc08204c000    [X X X X X X X X X X]
// 10      11      16      0xc08204c000    [X X X X X X X X X X X]
// 11      12      16      0xc08204c000    [X X X X X X X X X X X X]
// 12      13      16      0xc08204c000    [X X X X X X X X X X X X X]
// 13      14      16      0xc08204c000    [X X X X X X X X X X X X X X]
// 14      15      16      0xc08204c000    [X X X X X X X X X X X X X X X]
// 15      16      16      0xc08204c000    [X X X X X X X X X X X X X X X X]
// 16      17      32      0xc08204e000    [X X X X X X X X X X X X X X X X X]
// 17      18      32      0xc08204e000    [X X X X X X X X X X X X X X X X X X]
// 18      19      32      0xc08204e000    [X X X X X X X X X X X X X X X X X X X]
// 19      20      32      0xc08204e000    [X X X X X X X X X X X X X X X X X X X X]
```