BAB 12: Array — Koleksi Data Berukuran Tetap
Pelajari array di Go: cara mendeklarasikan, mengakses, dan mengiterasi koleksi data berukuran tetap. Pahami batasan array sebelum berkenalan dengan slice di bab berikutnya.
Di bab sebelumnya, kamu sudah menggunakan array [3]Mahasiswa dan [5]int di dalam loop untuk memproses data kelas. Kamu mungkin sudah merasakan polanya: ukuran array ditulis langsung di tipe datanya — [3], [4], [5]. Bab ini membahas array secara menyeluruh: apa yang bisa dilakukan, apa batasannya, dan bagaimana Go bekerja di baliknya.
Array di Go adalah koleksi elemen dengan tipe yang sama dan ukuran yang tetap. “Tetap” berarti ukurannya ditentukan saat deklarasi dan tidak bisa diubah saat program berjalan. Ini berbeda dari Python list atau JavaScript array yang bisa tumbuh bebas. Batasan ini bukan cacat — justru memberikan garansi memori yang predictable dan performa yang konsisten.
Deklarasi Array
Ada beberapa cara mendeklarasikan array di Go, semua valid — pilihannya tergantung konteks.
// main.go
package main
import "fmt"
func main() {
// deklarasi kosong — semua elemen terisi zero value
var suhu [5]float64
fmt.Println("Kosong:", suhu)
// deklarasi dengan nilai awal
nilai := [5]int{80, 75, 90, 85, 70}
fmt.Println("Dengan nilai:", nilai)
// biarkan Go hitung ukurannya dari jumlah elemen
kota := [...]string{"Jakarta", "Bandung", "Surabaya"}
fmt.Println("Kota:", kota)
fmt.Println("Jumlah kota:", len(kota))
}
Kosong: [0 0 0 0 0]
Dengan nilai: [80 75 90 85 70]
Kota: [Jakarta Bandung Surabaya]
Jumlah kota: 3
Sintaks [...] memerintahkan Go untuk menghitung jumlah elemen secara otomatis dari literal yang kamu tulis. Hasilnya identik dengan menulis angkanya secara eksplisit — hanya lebih ringkas.
Array var suhu [5]float64 yang belum diisi akan terisi 0 untuk numerik, "" untuk string, dan false untuk bool. Go menjamin ini — tidak ada nilai sampah dari memori seperti di C.
Akses dan Modifikasi
Elemen array diakses dengan indeks yang dimulai dari 0. Elemen terakhir selalu berada di indeks len(array) - 1.
// main.go
package main
import "fmt"
func main() {
nilai := [5]int{80, 75, 90, 85, 70}
fmt.Println("Nilai pertama:", nilai[0]) // 80
fmt.Println("Nilai terakhir:", nilai[4]) // 70
// ubah nilai di indeks tertentu
nilai[2] = 95
fmt.Println("Setelah diubah:", nilai)
}
Nilai pertama: 80
Nilai terakhir: 70
Setelah diubah: [80 75 95 85 70]
Mengakses indeks di luar batas array menyebabkan index out of range — program berhenti dengan panic. nilai[5] pada array berukuran 5 akan crash karena indeks valid hanya 0 sampai 4. Go mendeteksi ini saat runtime, bukan saat kompilasi.
Iterasi Array
Untuk mengiterasi array, kamu bisa menggunakan for klasik dengan counter atau for range. Keduanya sudah kamu kenal dari Bab 11.
// main.go
package main
import "fmt"
func main() {
nilai := [5]int{80, 75, 90, 85, 70}
// for klasik — gunakan jika butuh kontrol indeks penuh
fmt.Println("For klasik:")
for i := 0; i < len(nilai); i++ {
fmt.Printf(" nilai[%d] = %d\n", i, nilai[i])
}
// for range — lebih idiomatik, lebih aman
fmt.Println("\nFor range:")
for i, n := range nilai {
fmt.Printf(" indeks %d: %d\n", i, n)
}
}
For klasik:
nilai[0] = 80
nilai[1] = 75
nilai[2] = 90
nilai[3] = 85
nilai[4] = 70
For range:
indeks 0: 80
indeks 1: 75
indeks 2: 90
indeks 3: 85
indeks 4: 70
Prefer for range untuk iterasi biasa — lebih pendek dan tidak ada risiko salah menulis batas kondisi.
Array Multidimensi
Array bisa bersarang: array yang elemennya juga array. Paling umum digunakan untuk matriks dua dimensi.
// main.go
package main
import "fmt"
func main() {
// matriks 2x3: 2 baris, 3 kolom
matriks := [2][3]int{
{1, 2, 3},
{4, 5, 6},
}
fmt.Println("Matriks:")
for _, baris := range matriks {
for _, val := range baris {
fmt.Printf("%3d", val)
}
fmt.Println()
}
fmt.Printf("\nElemen [1][2]: %d\n", matriks[1][2])
}
Matriks:
1 2 3
4 5 6
Elemen [1][2]: 6
Array Sebagai Nilai, Bukan Referensi
Ini salah satu perilaku Go yang mengejutkan bagi yang datang dari bahasa lain: ketika kamu assign array ke variabel baru atau mengoper ke fungsi, Go menyalin seluruh isinya. Modifikasi pada salinan tidak memengaruhi array asli.
// main.go
package main
import "fmt"
func main() {
asli := [3]int{1, 2, 3}
salinan := asli // seluruh isi disalin
salinan[0] = 99
fmt.Println("Asli :", asli) // tidak berubah
fmt.Println("Salinan:", salinan) // berubah
}
Asli : [1 2 3]
Salinan: [99 2 3]
Perilaku ini membuat kode lebih mudah diprediksi — tapi bisa menjadi masalah performa jika array berukuran besar disalin terus-menerus.
Latihan
Latihan 1 — Statistik nilai:
Dari array [6]int{72, 88, 65, 91, 78, 84}, hitung nilai tertinggi, terendah, dan rata-ratanya menggunakan satu loop. Gunakan if dari Bab 10 untuk melacak nilai maksimum dan minimum.
Latihan 2 — Cari elemen:
Tulis program yang mencari apakah sebuah nama ada di dalam array [4]string{"Andi", "Sari", "Budi", "Rina"}. Gunakan variabel cari := "Budi" dan tampilkan di indeks berapa nama itu ditemukan, atau “tidak ditemukan” jika tidak ada. Gunakan break dari Bab 11 untuk berhenti begitu ditemukan.
Latihan 3 — Transpose matriks:
Buat matriks [2][3]int dengan nilai bebas, lalu cetak versi transposenya sebagai matriks [3][2]int. Transpose berarti baris jadi kolom dan kolom jadi baris.
Array dengan ukuran tetap sangat berguna ketika jumlah data sudah diketahui dari awal — daftar hari dalam seminggu, koordinat 2D, nilai-nilai konfigurasi tetap. Namun sebagian besar program nyata bekerja dengan data yang jumlahnya baru diketahui saat runtime: hasil query database, respons API, input dari user. Untuk kasus itu, Go menyediakan slice — struktur yang dibangun di atas array tapi bisa tumbuh dan menyusut secara dinamis.