スライスややこしいわ〜〜ほんま

## 今回のゴール

個人的にくそくそややこしかったスライスでの扱いを復習して腑に落ちた理解まで落とし込む。変な挙動して、悩んだので激おこぷんぷん丸(懐かしい、世代出るやん)

## 変数の名前が変な件

気しないでくれよな。Sorry Bro…

### スライスを切り取った時の要素数と容量について

サンプルコード

```main.go
  s11 := []int{11, 12, 13, 14, 15, 16, 17, 18} 
	s12 := s11[2:6]                              
	fmt.Println(s11, len(s11), cap(s11))
	fmt.Println(s12, len(s12), cap(s12))

// s11: [11 12 13 14 15 16 17 18] 8 8
// s12: [13 14 15 16] 4 6
```

　変数s12が13,14,15,16が欲しい場合、インデックス+1の関係よりs11[2:6]と記述する必要がある(インデックス6である17は含めない)。上記の要素数(length)と容量(capacity)を出力する。

自身はまずここであれ？ってなった。`s12の容量4じゃないの？`どうやら元のスライスの途中までを切り取っても容量については開始位置から最後までの数になるみたいです。

### スライスから切り取ったもののある要素を値を代入した時の挙動について

```main.go
  s11 := []int{11, 12, 13, 14, 15, 16, 17, 18} 
	s12 := s11[2:6]                              
	fmt.Println("s11:", s11, len(s11), cap(s11))
	fmt.Println("s12:", s12, len(s12), cap(s12))

	s12[0] = 555
	fmt.Println("s11:", s11, len(s11), cap(s11))
	fmt.Println("s12:", s12, len(s12), cap(s12))

// s11: [11 12 13 14 15 16 17 18] 8 8
// s12: [13 14 15 16] 4 6
// s11: [11 12 555 14 15 16 17 18] 8 8
// s12: [555 14 15 16] 4 6
```

　s12のインデックス0に555を代入してみました。その後のコンソールを観察すると参照したs11のインデックス2の値も555に変わってしまっていることがわかります。このことからs12それぞれは、s11から参照した値をコピーしていることがわかります。

### スライスの要素を追加した時の要素数と容量について

```main.go
  s11 := []int{11, 12, 13, 14, 15, 16, 17, 18} 
	s12 := s11[2:6]                              
	fmt.Println("s11:", s11, len(s11), cap(s11))
	fmt.Println("s12:", s12, len(s12), cap(s12))

	s12 = append(s12, 7, 8)
  fmt.Println("s11:", s11, len(s11), cap(s11))
	fmt.Println("s12:", s12, len(s12), cap(s12))

// s11: [11 12 13 14 15 16 17 18] 8 8
// s12: [13 14 15 16] 4 6
// s11: [11 12 13 14 15 16 7 8] 8 8
// s12: [13 14 15 16 7 8] 6 6
```

　s11から要素を切り取ったs12にappendメソッドを用いて7,8と要素を追加しました。するとlengthとcapacityはともに6になりました。しかし、s12はいいのですが、s11の16以降の数値が変更されるので意図しない変更が生まれますので、注意です。

そして、さらに要素を追加してみましょう。

```main.go
  s11 := []int{11, 12, 13, 14, 15, 16, 17, 18} 
	s12 := s11[2:6]                              
	fmt.Println("s11:", s11, len(s11), cap(s11))
	fmt.Println("s12:", s12, len(s12), cap(s12))

	s12 = append(s12, 7, 8, 999)
	fmt.Println("s11:", s11, len(s11), cap(s11))
	fmt.Println("s12:", s12, len(s12), cap(s12))

// s11: [11 12 13 14 15 16 17 18] 8 8
// s12: [13 14 15 16] 4 6
// s11: [11 12 13 14 15 16 17 18] 8 8
// s12: [13 14 15 16 7 8 999] 7 12
```

　先ほどの追加した要素を7,8,999の合計三つを追加しました。追加後のlengthとcapacityの様子がどうもおかしいですね〜。自身はここで「？？？」になりました。
　調査すると今回、要素を追加前のs12のcapacityは6で、この時lengthはすでに4ありました。appendで3つ要素を追加する時に、capacityを超えてしまうため、新たなメモリ上の配列を作成する。そこに元のcapacityの倍の数値になるみたいです。ちなみに、先ほどcapacityが不足していない時は、7,8が追加された時元のスライスの値も変更されていたのに対して、新しくメモリ上に配列を作成したこちらは変更されません。

### メモリ上で新たに作成された要素を代入した時の元のスライスとの挙動について

ここが一番わかりにくかったです。`スライスの要素を追加した時の要素数と容量について`の続きに操作を加えます。

```main.go
s11 := []int{11, 12, 13, 14, 15, 16, 17, 18} // 8,8
	s12 := s11[2:6]
	fmt.Println("s11:①", s11, len(s11), cap(s11))
	fmt.Println("s12:②", s12, len(s12), cap(s12))

	s12 = append(s12, 7, 8, 999)
	fmt.Println("s11:③", s11, len(s11), cap(s11))
	fmt.Println("s12:④", s12, len(s12), cap(s12))

  // 要素を加えて新たにメモリ上に作成された配列を参照しているs12の値を変更してみる
	s12[0] = 52
	fmt.Println("s11:⑤", s11, len(s11), cap(s11))
	fmt.Println("s12:⑥", s12, len(s12), cap(s12))

// s11:① [11 12 13 14 15 16 17 18] 8 8
// s12:② [13 14 15 16] 4 6
// s11:③ [11 12 13 14 15 16 17 18] 8 8
// s12:④ [13 14 15 16 7 8 999] 7 12
// s11:⑤ [11 12 13 14 15 16 17 18] 8 8
// s12:⑥ [52 14 15 16 7 8 999] 7 12
```

　続きで要素を加えて新たにメモリ上に作成された配列を参照しているs12の値を変更してみる。すると⑥のインデックス1の値がしっかりと変更されているのが観測されます。しかし、⑤のインデックス2は変更されていません。
　調査すると要素を追加する際、②の時点のcapacityを超える要素数を追加するとメモリ上で新しく作成する配列は参照するものが別ものになるみたいです。以上から、要素数などは同じではあるが参照しているものがかわるということみたい。

## 参考記事

[15. スライスのハマりどころ](https://www.techscore.com/tech/Go/Lang/Basic15/)

[Go 言語のスライス - Go 言語入門](https://golang.keicode.com/basics/go-slice.php)

[【Go】基本文法④(配列・スライス) - Qiita](https://qiita.com/k-penguin-sato/items/daad9986d6c42bdcde90)