Golangのスライス：makeがよくわからなかった件

Golangにはスライスってものがあるようです。
JavaでいうとArrayListに当たるのかな？
可変長配列らしいです。

初期化の方法としては、最初から値を入れるパターンと、入れないパターンとあると思うのですけど。

```ruby:初期化
   /* 初期値ありの場合 */
   retArray := []string{"a", "b"}
   /* 初期値なしの場合 */
   retArray := make([]string, 0, 0)
```

問題は、この「make」の引数。
公式を探そうにも、どう探したらいいかがよくわからない、、、
っていうか、GolangのAPI見にくい。。。

ってわけで、自分でいろいろ検証してみました。

#定義
参考にした元記事にはこんな感じに書いてました。

>
スライスは配列へのポインタ、長さ、キャパシティの3つの情報から構成されている。長さは要素数で、キャパシティはスライスの最初の要素から数えたときの参照先の配列の要素数。長さ、キャパシティはそれぞれlen、cap関数で取得することができる。
https://qiita.com/rock619/items/db44507d02814e490902
>

```ruby:makeの定義？
   変数名 := make([]入れる型（Generics的な？）, len(長さ), cap(キャパシティ))
```

、、、正直、ちんぷんかんぷんです。

#結論
先に結論を述べてしまうと、こんな感じ。
<img width="899" alt="スクリーンショット 2019-11-14 12.14.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/40e1d09b-6e45-c855-a7f5-3b3696bd3acb.png">

- lenは初期で作成される要素の数、capは確保される容量の数。
- len < cap になるような設定はダメ。（決められた容量を超えた要素は作れない）
- 容量を超えたデータを追加すると、元の倍の容量が自動で確保される。
<img width="764" alt="スクリーンショット 2019-11-14 13.13.30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/a19c4a5e-612b-f2ea-dbe3-ad6f102f4cfd.png">
<img width="819" alt="スクリーンショット 2019-11-14 13.15.09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/c7be66d8-b270-c38a-3ef6-9017517d865a.png">




#検証
len、capのところに、いろんな値を入れてみました。
で、デバッグで確かめてみたので、ちょっと見にくいですが、左がデバッグ、右がコードですー。
※ついでに、appendした時も見てみた。

## make([]string, 0, 0)
**make後**
 中身はなんもない。
<img width="717" alt="スクリーンショット 2019-11-14 11.29.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/b86c935c-39ef-439e-eac3-602e33621a5d.png">
**append後**
 [0]に値が追加された。
<img width="716" alt="スクリーンショット 2019-11-14 11.32.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/5be1808a-90ca-8710-3aa6-526d4fcf7231.png">

## make([]string, 0, 1)
**make後**
 中身はなんもない。
<img width="712" alt="スクリーンショット 2019-11-14 11.35.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/0d21f45c-e987-34c7-9c32-180d18547b19.png">
**append後**
 [0]に値が追加された？
<img width="739" alt="スクリーンショット 2019-11-14 11.37.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/acde9fd0-87c1-c767-c102-d9aea21352e8.png">

## make([]string, 0, 3)
**make後**
 中身はなんもない。
<img width="752" alt="スクリーンショット 2019-11-14 11.38.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/0f0968b1-0d77-9c22-25c4-a80bd353a29b.png">
**append後**
 [0]に値が追加された？
<img width="720" alt="スクリーンショット 2019-11-14 11.39.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/c51755cf-d165-fd1b-19e4-9768f2acbb36.png">

## make([]string, 2, 0)
怒られた。
len < cap になるのはダメらしい。
<img width="427" alt="スクリーンショット 2019-11-14 11.41.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/e56afee8-7e6a-ecef-f153-79c9b08370a3.png">

## make([]string, 2, 2)
**make後**
 既に箱が作られてる。
<img width="743" alt="スクリーンショット 2019-11-14 11.42.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/5b4402c1-acc0-da0f-1530-8b9102f96b84.png">
**append後**
 [２]に値が追加された。（次のインデックス？）
<img width="755" alt="スクリーンショット 2019-11-14 11.43.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/a07bfe68-733d-a3d8-9de0-b0cf76a9b91b.png">
　なんでcapが2増えたのか？については、直前のcapが「２」だったので、倍の「４」になったっぽい。
>
これはGo言語の仕様によるもので、容量オーバーしたら基本的に２倍（※追記参照）の値を確保します。
appendするたびに一々メモリ領域を確保してコピーする手順を踏むのは効率が悪いため
このような動作になっています。
https://qiita.com/Kashiwara/items/e621a4ad8ec00974f025
######2019/11/15 追記　（c-yan様、ありがとうございます！）　
正確には1024未満の時は2倍、それ以上の時は1.25倍とのことです。
ソース見たら、確かに。。。ソースもちゃんと見て仕様確認しないとですね:sweat:
https://github.com/golang/go/blob/master/src/runtime/slice.go#L100
ただ、このソースの「func　growslice」がどこから呼ばれてるのか、はまだ確認中です。。。
appendで呼ばれてそうな気もするんだけど、、、実装が見つからない。。。

```ruby:slice.go(抜粋）
	newcap := old.cap
	doublecap := newcap + newcap
	if cap > doublecap {
		newcap = cap
	} else {
		if old.len < 1024 {
			newcap = doublecap
		} else {
			// Check 0 < newcap to detect overflow
			// and prevent an infinite loop.
			for 0 < newcap && newcap < cap {
				newcap += newcap / 4
			}
			// Set newcap to the requested cap when
			// the newcap calculation overflowed.
			if newcap <= 0 {
				newcap = cap
			}
		}
	}
```

## make([]string, 2, ３)
検証のため、やってみた。
makeでは、要素２で作られた。
<img width="711" alt="スクリーンショット 2019-11-14 12.02.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/c400b57e-ceb0-2cd8-76b7-6ff24ac95ce9.png">
１個の用を追加したけど、容量内なので、capはそのまま
<img width="745" alt="スクリーンショット 2019-11-14 12.05.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/b2c55ffd-c37a-d2b0-79ec-b71b3ddf46bf.png">
もう１個追加したことで、容量オーバーに。
で、元の容量の倍の「６」が容量に設定された。
<img width="719" alt="スクリーンショット 2019-11-14 12.02.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/57994981-ffcf-80c4-1150-d6b6f71c8444.png">


#まとめ
使い方がなんとなくわかった。
capとかでメモリの管理もしているあたり、C言語がベース、って感じがする。
Javaらーにはまだまだ概念としてわかりにくい部分がきっとありそうだけど、
出会ったら検証していきますっ！