Sebuah slice digambarkan oleh dua angka yang berbeda peran: panjang (len) dan kapasitas (cap). Pemula sering mencampuradukkan keduanya, padahal salah mengira cap sebagai jumlah elemen bisa membuat program melewatkan bug halus di sekitar pemotongan dan penambahan data. Pada chapter ini kita membedah makna kedua angka tersebut, menghitung kapasitas hasil pemotongan, lalu mengamati sendiri bagaimana kapasitas slice tumbuh ketika elemen terus ditambahkan.
Panjang: Jumlah Elemen yang Terlihat #
len(s) mengembalikan jumlah elemen yang sedang terlihat dari slice s. Nilai ini menentukan indeks sah: elemen valid dibaca pada indeks 0 sampai len(s)-1. Panjang boleh berubah setiap kali slice dipotong atau ditambah elemen, dan len slice kosong maupun slice nil sama-sama 0.
Kapasitas: Ruang Simpan yang Tersedia #
cap(s) mengembalikan jumlah slot penyimpanan yang tersedia mulai dari elemen pertama slice sampai ujung penyimpanan di belakangnya. Angka ini adalah batas tumbuh tanpa realokasi: selama len masih di bawah cap, penambahan elemen cukup memakai slot sisa. Aturannya sederhana: len(s) selalu kurang dari atau sama dengan cap(s), dan keduanya tidak pernah bernilai negatif.
Membuat Slice dengan make #
Fungsi make memungkinkan kita memilih kedua angka tersebut sejak awal. Bentuk make([]int, 5) membuat slice dengan len 5 dan cap 5 yang seluruh elemennya sudah terisi zero value, sedangkan make([]int, 0, 5) membuat slice kosong dengan len 0 namun cap 5 — lima slot sudah disiapkan meski belum ada elemen yang terlihat.
penuh := make([]int, 5) // len 5, cap 5, isi [0 0 0 0 0]
siap := make([]int, 0, 5) // len 0, cap 5, tampil []Kapasitas Hasil Pemotongan #
Pemotongan menghasilkan slice dengan len sebesar high - low, tetapi cap-nya dihitung dari titik potong: kapasitas hasil sama dengan len(a) - low, yaitu sisa ruang dari elemen pertama potongan sampai ujung penyimpanan slice sumber. Untuk a berisi lima elemen, potongan a[1:3] memiliki len 2 dan cap 4, sedangkan a[2:5] memiliki len 3 dan cap 3. Rumus ini menjelaskan angka yang muncul pada program utuh di bawah.
Pertumbuhan Kapasitas #
Ketika append menambahkan elemen padahal cap sudah penuh, Go otomatis menyiapkan penyimpanan baru yang lebih besar, menyalin elemen lama, lalu mengembalikan slice yang menunjuk penyimpanan baru tersebut. Seberapa besar ruang baru yang disiapkan adalah strategi internal runtime; spesifikasi Go tidak menjanjikan angka tertentu, dan strategi ini pernah berubah antar versi Go.
Program Utuh #
Berkas capacity-demo.go memperagakan make dengan cap eksplisit, perhitungan kapasitas hasil pemotongan, dan pertumbuhan kapasitas lewat append berturut-turut. Sebagai pengantar singkat: append(s, elemen) menambah satu elemen di akhir slice dan mengembalikan slice hasil; pembahasan penuhnya menyusul pada chapter append dan copy
.
package main
import "fmt"
func main() {
// make dengan panjang dan kapasitas eksplisit: len 0, cap 5.
s := make([]int, 0, 5)
fmt.Printf("awal len=%d cap=%d\n", len(s), cap(s))
s = append(s, 1, 2)
fmt.Printf("setelah isi len=%d cap=%d\n", len(s), cap(s))
// Kapasitas hasil slicing: cap = len(a) - low.
a := []int{10, 20, 30, 40, 50}
b := a[1:3]
c := a[2:5]
fmt.Println("b :", b, "len:", len(b), "cap:", cap(b))
fmt.Println("c :", c, "len:", len(c), "cap:", cap(c))
// Pertumbuhan kapasitas ketika append melebihi ruang sisa.
tumbuh := make([]int, 0, 2)
fmt.Println("append 8 elemen satu per satu:")
for i := 1; i <= 8; i++ {
tumbuh = append(tumbuh, i)
fmt.Printf(" len=%d cap=%d\n", len(tumbuh), cap(tumbuh))
}
}Output yang Dihasilkan:
awal len=0 cap=5
setelah isi len=2 cap=5
b : [20 30] len: 2 cap: 4
c : [30 40 50] len: 3 cap: 3
append 8 elemen satu per satu:
len=1 cap=2
len=2 cap=2
len=3 cap=4
len=4 cap=4
len=5 cap=8
len=6 cap=8
len=7 cap=8
len=8 cap=8Mari kita telaah baris demi baris program di atas:
- Baris 7 (
s := make([]int, 0, 5)): membuat slicelen 0 cap 5; output pertama membuktikan kedua angka tersebut. - Baris 9 (
s = append(s, 1, 2)): dua elemen masuk sehinggalennaik menjadi 2, sementaracaptetap 5 karena masih ada slot sisa. - Baris 14 (
b := a[1:3]): potongan dua elemen[20 30];cap(b)bernilai 4 sesuai rumuslen(a) - low= 5 - 1. - Baris 15 (
c := a[2:5]): potongan tiga elemen[30 40 50];cap(c)bernilai 3 karena potongan dimulai dari indeks 2 sehingga hanya tersisa 5 - 2 = 3 slot. - Baris 18 (
tumbuh := make([]int, 0, 2)): slice mulai daricap2, cukup untuk dua elemen pertama. - Baris 20–24 (loop
append): elemen ketiga memaksa kapasitas naik dari 2 ke 4, dan elemen kelima menaikkannya lagi menjadi 8 — setiap realokasi menyediakan ruang berlipat dan salinan elemen lama dipindahkan ke penyimpanan baru.
Pola len yang naik satu-satu sementara cap melonjak berlipat adalah cara Go menjaga keseimbangan: penambahan elemen rata-rata murah karena ruang disiapkan duluan. Kita sudah melihat append berkali-kali bertugas menambah elemen; chapter berikutnya membedah append dan copy secara penuh, termasuk kebiasaan wajib mereassign hasil append.
Referensi #
- Go Blog: Arrays, slices (and strings): The mechanics of append — mekanisme pertumbuhan slice dan realokasi.
- Spesifikasi Go: Making slices, maps and channels
— aturan resmi fungsi
make. - Spesifikasi Go: Appending and copying slices
— definisi
append,len, dancap.
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
capacity-demo.go
Unduh berkaspackage main
import "fmt"
func main() {
// make dengan panjang dan kapasitas eksplisit: len 0, cap 5.
s := make([]int, 0, 5)
fmt.Printf("awal len=%d cap=%d\n", len(s), cap(s))
s = append(s, 1, 2)
fmt.Printf("setelah isi len=%d cap=%d\n", len(s), cap(s))
// Kapasitas hasil slicing: cap = len(a) - low.
a := []int{10, 20, 30, 40, 50}
b := a[1:3]
c := a[2:5]
fmt.Println("b :", b, "len:", len(b), "cap:", cap(b))
fmt.Println("c :", c, "len:", len(c), "cap:", cap(c))
// Pertumbuhan kapasitas ketika append melebihi ruang sisa.
tumbuh := make([]int, 0, 2)
fmt.Println("append 8 elemen satu per satu:")
for i := 1; i <= 8; i++ {
tumbuh = append(tumbuh, i)
fmt.Printf(" len=%d cap=%d\n", len(tumbuh), cap(tumbuh))
}
}