Cap and Length in Go Slice

original := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
// original: len=10, cap=10

slice1 := original[2:6] // [3,4,5,6]
// slice1: len=4, cap=8 (karena mulai dari index 2, sisa capacity = 10-2 = 8)

slice2 := slice1[1:4] // [4,5,6]
// slice2: len=3, cap=7 (ini yang menjadi pertanyaan)

Mengapa Capacity = 7?

Kunci pemahamannya: Capacity dihitung dari pointer awal slice sampai akhir array underlying.

  1. Array Underlying: [1,2,3,4,5,6,7,8,9,10] (capacity = 10)

  2. Slice1 (original[2:6]):

    • Pointer: index 2 (nilai 3)

    • Length: 4 elemen (index 2-5: [3,4,5,6])

    • Capacity: 8 (dari index 2 sampai akhir array: 10-2 = 8)

  3. Slice2 (slice1[1:4]):

    • Pointer: index 1 dari slice1 (yang sebenarnya index 3 dari array underlying)

    • Length: 3 elemen ([4,5,6])

    • Capacity: 7 (dari index 3 sampai akhir array: 10-3 = 7)

Visualisasi

Array Underlying: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Indeks:           0  1  2  3  4  5  6  7  8  9

original:        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
                 ↑  ↑  ↑  ↑  ↑  ↑  ↑  ↑  ↑  ↑
                 seluruh array (cap=10)

slice1: original[2:6] β†’ [3,4,5,6]
                 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
                          ↑  ↑  ↑  ↑
                          slice1 (len=4, cap=8)
                          Pointer di index 2, sisa capacity sampai index 9 = 8

slice2: slice1[1:4] β†’ [4,5,6]
                 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
                             ↑  ↑  ↑
                             slice2 (len=3, cap=7)
                             Pointer di index 3, sisa capacity sampai index 9 = 7

Contoh Kode untuk Memperjelas

package main

import "fmt"

func main() {
    original := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    
    fmt.Printf("Original: %v, len: %d, cap: %d\n", original, len(original), cap(original))
    
    slice1 := original[2:6] // [3,4,5,6]
    fmt.Printf("slice1 (original[2:6]): %v\n", slice1)
    fmt.Printf("  Pointer menunjuk ke: %d (index 2 dari original)\n", original[2])
    fmt.Printf("  len: %d, cap: %d (10 - 2 = 8)\n", len(slice1), cap(slice1))
    
    slice2 := slice1[1:4] // [4,5,6]
    fmt.Printf("slice2 (slice1[1:4]): %v\n", slice2)
    fmt.Printf("  Pointer menunjuk ke: %d (index 3 dari original)\n", original[3])
    fmt.Printf("  len: %d, cap: %d (10 - 3 = 7)\n", len(slice2), cap(slice2))
    
    // Bukti bahwa mereka share array yang sama
    fmt.Println("\n=== Membuktikan Shared Array ===")
    slice2[0] = 999 // Ubah element pertama slice2
    fmt.Printf("Setelah ubah slice2[0] = 999:\n")
    fmt.Printf("slice2: %v\n", slice2)
    fmt.Printf("slice1: %v\n", slice1)
    fmt.Printf("original: %v\n", original)
}

Output:

Original: [1 2 3 4 5 6 7 8 9 10], len: 10, cap: 10
slice1 (original[2:6]): [3 4 5 6]
  Pointer menunjuk ke: 3 (index 2 dari original)
  len: 4, cap: 8 (10 - 2 = 8)
slice2 (slice1[1:4]): [4 5 6]
  Pointer menunjuk ke: 4 (index 3 dari original)
  len: 3, cap: 7 (10 - 3 = 7)

=== Membuktikan Shared Array ===
Setelah ubah slice2[0] = 999:
slice2: [999 5 6]
slice1: [3 999 5 6]
original: [1 2 3 999 5 6 7 8 9 10]

Rumus Umum Capacity

Untuk slice original[start:end]:

  • Length = end - start

  • Capacity = cap(original) - start

Jadi dalam kasus ini:

  • slice1 = original[2:6] β†’ cap = 10 - 2 = 8

  • slice2 = slice1[1:4] β†’ slice1 punya cap = 8, start = 1

  • Tapi ingat! slice1[1] sebenarnya adalah original[3]

  • Jadi cap(slice2) = cap(original) - 3 = 10 - 3 = 7

Inilah mengapa capacity menjadi 7 - karena dihitung dari pointer awal slice terhadap array underlying, bukan dari slice parent-nya.

Last updated