Map yang hanya berisi data belum cukup: program nyata perlu menambah pendaftar baru, memperbarui skor, menghapus entri kadaluarsa, dan memastikan sebuah key memang ada sebelum dipakai. Go menyediakan operasi bawaan untuk semuanya dengan sintaks yang ringkas. Pada chapter ini kita menuntaskan operasi dasar map, lalu menyelam satu level lebih dalam ke perilaku iterasi yang urutannya diacak serta sifat map sebagai reference saat dilewatkan ke fungsi.
Menambah dan Mengubah #
Penulisan m[key] = nilai sekaligus menangani dua kebutuhan: bila key belum ada, pasangan baru disimpan; bila key sudah ada, nilai lamanya diganti. Perilaku upsert ini membuat kode pembaruan tidak perlu memeriksa keberadaan key terlebih dahulu, misalnya skor["Budi"] = 45 valid baik Budi sudah tercatat maupun belum.
Menghapus dengan delete #
Built-in delete(m, key) menghapus pasangan key-value dari map. Fungsi ini tidak mengembalikan apa pun dan aman dipanggil untuk key yang memang tidak ada — penghapusan key absen bukanlah galat, map tetap tidak berubah. Kapasitas internal map tidak mengecil setelah penghapusan; key yang hilang benar-benar tidak lagi terbaca lewat len maupun iterasi.
Comma-Ok Idiom #
Pembacaan satu nilai nilai := m[key] tidak bisa membedakan dua keadaan: key ada dengan nilai 0, atau key memang tidak ada (zero value juga 0). Go menyediakan bentuk kedua yang mengembalikan nilai tambahan bertipe bool:
nilai, ada := m["Siti"] // 55, true -> key ada
nilai, ada = m["Andi"] // 0, false -> key tidak adaVariabel kedua lazim dinamai ok atau ada dan langsung dipakai dalam if:
if nilai, ok := m["Siti"]; ok {
fmt.Println("skor Siti:", nilai)
}Sintaks if dengan initializer semacam ini sudah kita kenal dari chapter If dengan Initializer
. Jumlah elemen map dibaca dengan len(m) sama seperti slice.
Iterasi yang Terurut #
Urutan iterasi map dengan for ... range diacak oleh runtime Go sejak desainnya, agar program tidak diam-diam bergantung pada urutan tertentu. Untuk output yang stabil, urutkan key terlebih dahulu. Idiom modernnya memakai dua package standard library: maps.Keys(m) menghasilkan iterator seluruh key, dan slices.Sorted menerima iterator tersebut lalu mengembalikan slice key yang sudah terurut:
for _, nama := range slices.Sorted(maps.Keys(skor)) {
fmt.Printf("%s=%d\n", nama, skor[nama])
}Map adalah Reference #
Berbeda dengan array yang disalin utuh, map berperilaku sebagai reference: variabel map menyimpan penunjuk ke struktur data internal. Ketika map dilewatkan sebagai argumen fungsi, fungsi menerima penunjuk ke struktur yang sama, sehingga m[nama] += 10 di dalam fungsi terlihat oleh pemanggil tanpa perlu mengembalikan map. Sifat ini menjelaskan kenapa fungsi seperti delete dan tambahPoin pada program di bawah langsung mengubah data pemanggil.
Program Utuh #
Berkas operasi-map-demo.go merangkai seluruh operasi dalam satu program. Jalankan dengan go run operasi-map-demo.go dari direktori chapter:
package main
import (
"fmt"
"maps"
"slices"
)
// tambahPoin mengubah map dari dalam fungsi: perubahan terlihat pemanggil.
func tambahPoin(m map[string]int, nama string) {
m[nama] += 10
}
func main() {
skor := map[string]int{"Budi": 40, "Siti": 55, "Andi": 30}
// Menambah key baru dan mengubah key lama.
skor["Budi"] = 45
skor["Rina"] = 60
fmt.Println("skor:", skor)
// Menghapus key.
delete(skor, "Andi")
fmt.Println("setelah delete:", skor)
// Comma-ok: membedakan key kosong dari key yang tidak ada.
nilai, ada := skor["Siti"]
fmt.Println("Siti:", nilai, "ada:", ada)
nilai, ada = skor["Andi"]
fmt.Println("Andi:", nilai, "ada:", ada)
// len menghitung jumlah key di dalam map.
fmt.Println("len(skor):", len(skor))
// Iterasi terurut: kunci diurutkan sebelum dicetak.
for _, nama := range slices.Sorted(maps.Keys(skor)) {
fmt.Printf("%s=%d\n", nama, skor[nama])
}
// Map bersifat reference: perubahan di fungsi terlihat di sini.
tambahPoin(skor, "Budi")
fmt.Println("Budi setelah tambahPoin:", skor["Budi"])
}Output yang Dihasilkan:
skor: map[Andi:30 Budi:45 Rina:60 Siti:55]
setelah delete: map[Budi:45 Rina:60 Siti:55]
Siti: 55 ada: true
Andi: 0 ada: false
len(skor): 3
Budi=45
Rina=60
Siti=55
Budi setelah tambahPoin: 55Mari kita telaah baris demi baris program di atas:
- Baris 6–8 (
func tambahPoin): menerima map dan menaikkan nilai satu key; parameter tidak menyalin isi map, melainkan berbagi struktur data yang sama dengan pemanggil. - Baris 16–18 (
skor["Budi"] = 45,skor["Rina"] = 60): penugasan yang pertama mengubah key lama, yang kedua menambah key baru — keduanya memakai sintaks yang sama. - Baris 21 (
delete(skor, "Andi")): menghapus key"Andi"; output berikut membuktikan isi map menyusut menjadi tiga pasangan. - Baris 25–28 (comma-ok): pembacaan
"Siti"menghasilkan55, truekarena key ada; pembacaan"Andi"menghasilkan0, falsemeskipun key itu pernah ada sebelum dihapus. - Baris 34–36 (
slices.Sorted(maps.Keys(skor))): key diurutkan lebih dulu sehingga pasangan tercetakBudi,Rina,Sitisecara stabil di setiap eksekusi. - Baris 39–40 (
tambahPoin(skor, "Budi")): skor Budi naik dari 45 menjadi 55 dan perubahan terlihat dimain— bukti map tidak disalin saat dilewatkan ke fungsi.
Satu sisi map masih tersisa dan sering menjebak pemula: apa yang terjadi ketika variabel map nilah yang tidak pernah diinisialisasi dengan make atau literal. Chapter berikutnya membedah slice dan map bernilai nil beserta batas operasinya.
Referensi #
- Go Blog: Maps in action (maps) — pembahasan resmi operasi map dan urutan iterasi.
- Dokumentasi package maps
— fungsi
Keys,Values, dan kolega. - Dokumentasi package slices
— fungsi
Sorteduntuk mengurutkan iterator key. - Spesifikasi Go: Map types — definisi resmi akses index map dan comma-ok.
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
operasi-map-demo.go
Unduh berkaspackage main
import (
"fmt"
"maps"
"slices"
)
// tambahPoin mengubah map dari dalam fungsi: perubahan terlihat pemanggil.
func tambahPoin(m map[string]int, nama string) {
m[nama] += 10
}
func main() {
skor := map[string]int{"Budi": 40, "Siti": 55, "Andi": 30}
// Menambah key baru dan mengubah key lama.
skor["Budi"] = 45
skor["Rina"] = 60
fmt.Println("skor:", skor)
// Menghapus key.
delete(skor, "Andi")
fmt.Println("setelah delete:", skor)
// Comma-ok: membedakan key kosong dari key yang tidak ada.
nilai, ada := skor["Siti"]
fmt.Println("Siti:", nilai, "ada:", ada)
nilai, ada = skor["Andi"]
fmt.Println("Andi:", nilai, "ada:", ada)
// len menghitung jumlah key di dalam map.
fmt.Println("len(skor):", len(skor))
// Iterasi terurut: kunci diurutkan sebelum dicetak.
for _, nama := range slices.Sorted(maps.Keys(skor)) {
fmt.Printf("%s=%d\n", nama, skor[nama])
}
// Map bersifat reference: perubahan di fungsi terlihat di sini.
tambahPoin(skor, "Budi")
fmt.Println("Budi setelah tambahPoin:", skor["Budi"])
}