Array & Slice — Go

Array & Slice di Go Array (Ukuran Tetap) Array di Go memiliki ukuran yang tidak bisa berubah setelah dideklarasikan: var angka [3]int = [3]int{10, 20, 30} //…

Array dan slice sama-sama menyimpan banyak nilai bertipe sama secara berurutan, dan isinya diambil lewat index yang mulai dari 0. Bedanya: jumlah slot array tetap, slice bisa bertambah. Bayangin Warung Bakso Mas Bimo. Mejanya ada 3 dan dipaku ke lantai: mau meja keempat berarti bongkar warung. Itu array. Buku nota pesanannya bisa terus ditulisi, dan kalau halamannya penuh, Mas Bimo pindah ke buku yang lebih tebal lalu menyalin semua catatan lama. Itu slice.

🧪 Tebakan cepat: pesanan := []string{"Bakso urat", "Mie ayam", "Es teh"}, lalu salinan := pesanan, lalu salinan[0] = "Bakso telur". Apa isi pesanan sekarang: masih Bakso urat di depan, atau ikut jadi Bakso telur? Tebak dulu, jawabannya ada di bagian "Slice berbagi array di belakangnya".

Array: jumlah slotnya tetap

meja := [3]string{"Sari", "Andi", "Dina"}
fmt.Println(meja)      // [Sari Andi Dina]
fmt.Println(meja[0])   // Sari
fmt.Println(len(meja)) // 3

cadangan := meja
cadangan[0] = "Rudi"
fmt.Println(meja, cadangan) // [Sari Andi Dina] [Rudi Andi Dina]

Slice: daftar yang bisa bertambah

pesanan := []string{"Bakso urat", "Mie ayam", "Es teh"}
fmt.Println(len(pesanan), cap(pesanan)) // 3 3

pesanan = append(pesanan, "Kerupuk")
fmt.Println(pesanan)                    // [Bakso urat Mie ayam Es teh Kerupuk]
fmt.Println(len(pesanan), cap(pesanan)) // 4 6

Di belakang tiap slice ada sebuah array. Selama masih ada slot kosong, append langsung mengisinya. Kalau sudah penuh, Go bikin array baru yang lebih besar, menyalin isi lama ke sana, baru menambah item barunya:

Sesudah len cap Yang terjadi
awal 3 3 array 3 slot, penuh
append "Kerupuk" 4 6 penuh, jadi pindah ke array baru 6 slot
append "Es jeruk" 5 6 ada slot kosong, langsung diisi
append "Teh panas" 6 6 slot terakhir terisi
append "Air" 7 12 penuh lagi, pindah ke array 12 slot

Untuk slice kecil kapasitasnya kira-kira dua kali lipat. Angka persisnya urusan runtime Go, jadi jangan dijadikan patokan. Kalau sudah tahu kira-kira butuh berapa, siapkan dari awal: make([]int, 0, 10) bikin slice kosong (len 0) dengan cap 10.

Slicing: ambil potongan dengan [awal:akhir]

angka := []int{10, 20, 30, 40, 50}
fmt.Println(angka[1:4]) // [20 30 40]
fmt.Println(angka[:3])  // [10 20 30]
fmt.Println(angka[3:])  // [40 50]

Slice berbagi array di belakangnya

Slice gak memegang isinya sendiri. Dia cuma jendela ke sebuah array: penunjuk ke array itu, plus len dan cap. salinan := pesanan menyalin jendelanya, bukan isinya, jadi dua-duanya melihat array yang sama:

pesanan := []string{"Bakso urat", "Mie ayam", "Es teh"}
salinan := pesanan
salinan[0] = "Bakso telur"
fmt.Println(pesanan) // [Bakso telur Mie ayam Es teh]

pesanan ikut berubah. Itu jawaban tebakannya, dan kebalikan dari array tadi. Slicing juga begitu: dengan a := []int{1, 2, 3, 4, 5} dan b := a[1:3], slot b[0] adalah slot a[1] yang sama, jadi b[0] = 99 membuat fmt.Println(a) mencetak [1 99 3 4 5].

Begitu append pindah ke array baru, keduanya berpisah: slice yang di-append menunjuk ke array baru, slice lainnya masih ke array lama. Perubahan di satu gak kelihatan lagi di yang lain.

Index di luar batas: panic

Index yang valid cuma 0 sampai len - 1. Lewat dari itu, program berhenti dengan panic:

pesanan := []string{"Bakso urat", "Mie ayam", "Es teh"}
i := 5
fmt.Println(pesanan[i])
panic: runtime error: index out of range [5] with length 3

goroutine 1 [running]:
main.main()
	/app/main.go:8 +0x1d
exit status 2

💡 append bisa menimpa isi slice lain

Kalau potongan masih punya slot sisa di array yang sama, append menulis ke slot itu, dan slice lain yang memakai slot tersebut ikut berubah:

a := []int{1, 2, 3, 4, 5}
c := a[:2]        // [1 2], tapi cap-nya 5
c = append(c, 77) // ditulis ke slot a[2]
fmt.Println(a)    // [1 2 77 4 5]

Butuh salinan yang benar-benar terpisah? Salin isinya ke slice baru: b := append([]int{}, a[1:3]...), atau b := make([]int, 2) lalu copy(b, a[1:3]).

⚠️ Jebakan yang sering ketemu

TL;DR: Array [3]string punya jumlah slot tetap dan disalin utuh saat di-assign. Slice []string bisa bertambah dengan x = append(x, item) (hasilnya wajib ditampung), punya len (jumlah isi) dan cap (slot di array belakangnya), dan pindah ke array baru yang lebih besar saat penuh. x[awal:akhir] mengambil potongan tanpa index akhir. Slice yang di-assign atau dipotong berbagi array yang sama, jadi perubahan lewat satu kelihatan di yang lain. Index di luar 0 sampai len - 1 bikin panic: index out of range [5] with length 3.

Yang akan kamu pelajari