スライスの理解で一番大事なのが
-
appendすると何が起きるのか? -
lenとcapの違いは? - スライス式(
a[i:j])でcapが変わるのはなぜ?
という部分です。
この記事では、サンプルコードを動かしながら
append / make / len / cap と、capの考え方を整理します。
1. はじめに
この記事でわかること:
-
appendの基本 -
make([]T, len, cap)の意味 -
lenとcapの違い - スライス式と
capの関係(ここが落とし穴)
2. appendの基本
a := []int{100,200}
a =append(a,300)
fmt.Println(a)// [100 200 300]
ポイント
-
appendは 戻り値を受け取る必要がある -
append(a, ...)は 新しいスライスを返す(同じ配列を使う場合もあるし、再確保される場合もある)
3. make と len / cap の確認
スライスは make で作るのが定番です。
l :=make([]int,0,5)
fmt.Println(l)// []
fmt.Printf("len=%d cap=%d value=%v\n",len(l),cap(l), l)// len=0 cap=5 value=[]
make の意味
make([]int,len,cap)
-
len:今使える要素数(実体として存在する長さ) -
cap:内部配列として確保している容量(appendで増える余地)
4. appendでlenが増える(capの範囲内)
l :=make([]int,0,5)
l =append(l,0,0)
fmt.Printf("len=%d cap=%d value=%v\n",len(l),cap(l), l)// len=2 cap=5 value=[0 0]
- len は 2 に増える
- cap は 5 のまま(まだ余裕がある)
5. capを超えたらどうなる?
l =append(l,1,2,3,4,5)
fmt.Printf("len=%d cap=%d value=%v\n",len(l),cap(l), l)
- len は増える
- cap は 足りなくなったら増える
⚠️ capの増え方(例:5→10など)は保証されません
環境やGoバージョンによって異なる可能性があります。
6. make([]int, 3) の場合
capを指定しない場合は、len==cap になります。
e :=make([]int,3)
fmt.Printf("len=%d cap=%d value=%v\n",len(e),cap(e), e)// len=3 cap=3 value=[0 0 0]
7. スライス式とcapの関係
スライス式 a[i:j] で作ったスライスは、元の配列を参照します。
そして capは「開始位置から元配列末尾まで」 になります。
7-1. 末尾寄りのスライス(capが小さい)
test := []int{1,2,3,4,5,6}
test2 := test[4:]
fmt.Println(test2)// [5 6]
fmt.Printf("len=%d, cap=%d\n",len(test2),cap(test2))// len=2 cap=2
理由:
-
開始位置が index=4
-
元配列の末尾(index=5)までしか残っていない
→ cap が 2 になる
7-2. 先頭寄りのスライス(capが大きい)
test3 := []int{1,2,3,4,5,6}
test4 := test3[:2]
fmt.Println(test4)// [1 2]
fmt.Printf("len=%d, cap=%d\n",len(test4),cap(test4))// len=2 cap=6
理由:
-
開始位置が index=0
-
元配列の末尾まで全部が「容量として残っている」
→ cap が 6 になる
7-3. 中間のスライス(lenとcapがずれる)
test5 := []int{1,2,3,4,5,6}
test6 := test5[3:4]
fmt.Println(test6)// [4]
fmt.Printf("len=%d, cap=%d\n",len(test6),cap(test6))// len=1 cap=3
理由:
-
len は
4 - 3 = 1 -
cap は「開始位置 3 から末尾まで」
→ index=3,4,5 の3つ分なので cap=3
8. まとめ
-
appendは戻り値を受け取る -
lenは「今の要素数」、capは「確保している容量」 -
make([]T, len)はlen==cap -
capを超えると内部配列が再確保される(増え方は保証されない) - スライス式
a[i:j]の cap は i(開始位置)から末尾まで になる