Go のスライスのスライシング(部分切り出し)
スライスの一部を切り出して新しいスライスを作る操作を「スライシング」と呼びます。配列やスライスから部分的なビューを作成する基本的な操作です。
基本のスライス式
s[low:high] の形式で、インデックス low から high-1 までの要素を含む新しいスライスを作成します。
numbers := []int{0, 1, 2, 3, 4, 5}
slice := numbers[2:5]
fmt.Println(slice) // [2 3 4]low は含まれ、high は含まれません(半開区間)。この動作は Python などの他言語と同じです。
インデックスの省略
low または high を省略できます。省略した場合、それぞれ先頭または末尾を意味します。
numbers := []int{0, 1, 2, 3, 4, 5}
fmt.Println(numbers[:3]) // [0 1 2] 先頭から3つ
fmt.Println(numbers[3:]) // [3 4 5] 3番目から末尾
fmt.Println(numbers[:]) // [0 1 2 3 4 5] 全体のコピーs[:] は元のスライスと同じ内容のスライスを返しますが、背後の配列を共有している点に注意が必要です。
配列からスライスを作る
配列に対してスライス式を適用すると、スライスが作成されます。
arr := [5]int{10, 20, 30, 40, 50}
slice := arr[1:4]
fmt.Println(slice) // [20 30 40]この方法で作成したスライスは、元の配列を背後の配列として共有します。
スライスしたスライスの容量
スライシングで作成したスライスの容量は、元のスライスの容量から low を引いた値になります。
original := make([]int, 5, 10)
for i := range original {
original[i] = i
}
slice := original[2:4]
fmt.Printf("len=%d cap=%d\n", len(slice), cap(slice))
// len=2 cap=8容量が 8 になるのは、元の容量 10 から先頭のインデックス 2 を引いた値です。
フルスライス式(3インデックス形式)
s[low:high:max] の形式を使うと、容量も制限できます。
original := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
slice := original[2:5:7]
fmt.Println(slice) // [2 3 4]
fmt.Printf("len=%d cap=%d\n", len(slice), cap(slice)) // len=3 cap=53番目のインデックス max は、容量の上限を指定します。容量は max - low で計算されます。この例では 7 - 2 = 5 です。
フルスライス式の用途
フルスライス式は、元のスライスへの意図しない影響を防ぐために使います。
original := []int{0, 1, 2, 3, 4, 5}
// 通常のスライス:appendで元の配列に影響する可能性がある
normal := original[2:4]
normal = append(normal, 999)
fmt.Println(original) // [0 1 2 3 999 5] ← 変更される
// フルスライス式:容量を制限してappendで新しい配列を確保させる
original = []int{0, 1, 2, 3, 4, 5}
limited := original[2:4:4]
limited = append(limited, 999)
fmt.Println(original) // [0 1 2 3 4 5] ← 変更されない容量を長さと同じに制限することで、append 時に必ず新しい配列が確保されるようになります。元のスライスを変更したくない場合に有効なテクニックです。