スライスとキャパシティについて詳しく解説

こんにちはnasustです。

Go言語 / golangのSliceについて詳しく解説します。

Sliceとは

Sliceとは配列の参照と長さを持っています。Sliceは配列と同じ様にアクセスできるのでSliceと意識せずに操作することが出来ます。

しかし配列とまったく同様に扱うとバグの元になりますので注意が必要です。

numbers := []int{ 1 , 2 , 3 , 4 , 5 , 6}

上記の例で、初期かで何が起こるか解説します。

  1. Sliceはキャパシティが6の配列を用意します。
  2. Sliceは配列の参照を持っています。
  3. Sliceの長さは6になります。
  4. Sliceは初期値をセットします。

次にappend関数で要素を追加した時の振る舞いを解説します。

キャパシティを超える様に追加

numbersA := []int{ 1 , 2 , 3 , 4 , 5 , 6} //キャパシティ 6
numbersB := append( numbersA , []int{ 7 , 8} ... ) //キャパシティ超える
cap(numbersA)//キャパシティ 6 lenは6
cap(numbersB)//キャパシティ 12 lenは8

numbersAにappend関数でキャパシティを超える様に追加すると、numbersAの2倍の配列のキャパシティを持ったnumbersBを返します。

何故、numbersBはnumbersAの2倍の配列のキャパシティを用意するのかは要素の追加時に効率を良くする為です。

例えばnumbersB Sliceに一個の要素を追加した場合、キャパシティの範囲内ですので、新たに配列を拡張せずに追加することができます。

もしキャパシティが無い場合は毎回メモリのアロケーションする為に負荷が掛かります。

キャパシティを超え無い様に追加した時は配列の参照は元のまま

numbersA := []int{ 1 , 2 , 3 , 4 , 5 , 6} //キャパシティ 6
numbersB := append( numbersA , []int{ 7 , 8} ) //キャパシティ超える
cap(numbersA)//キャパシティ 6 lenは6
cap(numbersB)//キャパシティ 12 lenは8
numbersC := append( numbersB , []int{ 9 , 10 } ... ) //キャパシティ超えない。numbersBと同じ配列を参照している。lenは10
numbersC[0] = 99

fmt.Println("A:" , numbersA ) //A:  [1 2 3 4 5 6]
fmt.Println("B:" , numbersB ) //B:  [99 2 3 4 5 6 7 8]
fmt.Println("C:" , numbersC ) //C:  [99 2 3 4 5 6 7 8 9 10]

上記の例では、append関数でnumbersBにキャパシティを超えない様に要素を追加した新しいnumbersCが出来ました。そしてnumbersC[0] = 99しています。この時、numbersBとnumbersCはキャパシティを超えていないので、同じ配列を参照しています。ですのでnumbersB[0]も99になります。

まとめ

Sliceを扱う場合は、キャパシティを意識してSliceがどの配列を参照しているか注意しましょう。
Sliceを関数に値渡して操作した場合、キャパシティの問題で把握できなくなる可能性があります。 その時はポインタで渡して解決することが出来ますが、ややこしいので関数内では操作しないか、または配列をコピーしたSliceを使用するようにしましょう。

iOS、Android、Web、APIサーバーなどのフロントエンド・バックエンドを開発するソフトウェアエンジニアです。 UI/UXが好きです。かっこいいUIやWebデザインを眺めるのが趣味です。 このブログはソフトウェア開発関係の内容を記事にしています。
web service:
GitHubQiitaTwitterはてなブログ
handle name:
nasust
real name:
hideki mori
job:
ソフトウェアエンジニア
develop:
target: ios, android, web page, single page application, api server, system service, cli tool, linux embedded device

lang: c/c++, go, swift, objective-c, java, kotlin, typescript, dart, javascript, ruby, python, php

tool: vscode, xcode, android studio, photoshop, vim, docker