GO言語のスライス(Slice)は、動的なサイズを持つ配列のような構造です。スライスは、配列よりも柔軟にデータを管理することができ、Go言語におけるデータの扱いをより効率的にします。スライスの「長さ(length)」と「容量(capacity)」は、この柔軟性の核となる概念です。
スライスの長さ(Length)
スライスの「長さ」とは、スライスが現在含んでいる要素の数です。len()関数を使用してこの値を取得できます。例えば、
package main
import "fmt"
func main() {
s := []int{1, 2} // 長さが2のスライスを作成
fmt.Println(len(s))// 長さ
}
2
スライスの容量(Capacity)
スライスの「容量」とは、スライスが背後で確保している配列のサイズです。これは、スライスに追加可能な要素の最大数を意味し、cap()関数によって取得できます。容量は、スライスに新たな要素を追加する際に、背後の配列が再割り当てされるかどうかを決定する重要な要素です。
例えば、
package main
import "fmt"
func main() {
s := make([]int, 3, 10) // 容量10のスライスを作成
fmt.Println(cap(s))// 容量
}
10
長さと容量の動的変化
スライスに要素を追加すると(例:append()関数を使用)、その長さが増加します。もし追加によって長さが容量を超える場合、Goは新しい、より大きな容量を持つ配列を確保し、既存の要素を新しい配列にコピーした後、新しい要素を追加します。このプロセスは透過的に行われ、スライスを使用する側は容量の管理を意識する必要はありません。
package main
import "fmt"
func main() {
s := []int{1, 2} // 初期データ[1 2] がスライスを作成
fmt.Println((s))
s = append(s, 3) // 3をスライスsに追加
fmt.Println((s))
}
[1 2]
[1 2 3]
容量の初期設定と成長
スライスを作成する際に、容量は指定することも、指定しないこともできます。容量を指定しない場合、Goは自動的に管理します。スライスの容量は、通常、要素が追加されるたびに倍増します。これにより、大量の要素を追加する際のメモリ再割り当ての回数を減らし、パフォーマンスを向上させることができます。
package main
import "fmt"
func main() {
s := []int{1, 2} // 長さと容量が2のスライスを作成
fmt.Println(len(s)) // 長さ
fmt.Println(cap(s)) // 容量
fmt.Println((s))
s = append(s, 3) // 3をスライスsに追加
fmt.Println(len(s)) // 長さ
fmt.Println(cap(s)) // 容量 2倍になるので、2 * 2 =4
fmt.Println((s))
}
2
2
[1 2]
3
4
[1 2 3]
まとめ
スライスの長さと容量は、Go言語におけるデータ構造の柔軟性と効率性を支える重要な概念です。長さはスライスが現在持っている要素の数を、容量はスライスが背後で確保している配列のサイズを表します。Goはこれらの概念をうまく抽象化しており、開発者は効率的なデータ操作を容易に行うことができます。