Map menyimpan pasangan key dan value: kamu kasih key-nya, map langsung kasih value-nya, tanpa menelusuri isinya satu per satu. Bayangin daftar harga di dinding Warung Bakso Mas Bimo. Pembeli tanya "Es teh berapa?", Mas Bimo langsung melihat baris Es teh: 5.000. Nama menu itu key, harganya value. Di JavaScript ini mirip object; bedanya, di Go semua key satu tipe dan semua value satu tipe.
🧪 Tebakan cepat:
Es jerukgak ada di daftar harga.fmt.Println(harga["Es jeruk"])hasilnya apa: error,nil, atau0? Tebak dulu, jawabannya ada di bagian "Key yang gak ada: zero value dan comma-ok".
Bikin map
harga := map[string]int{
"Bakso urat": 15000,
"Mie ayam": 12000,
"Es teh": 5000,
}
fmt.Println(harga) // map[Bakso urat:15000 Es teh:5000 Mie ayam:12000]
fmt.Println(harga["Bakso urat"]) // 15000
fmt.Println(len(harga)) // 3
map[string]intartinya key-nya string dan value-nya int.- Tiap pasangan ditulis
key: value, dan baris terakhir juga diakhiri koma. harga["Bakso urat"]mengambil value dari key itu.len(harga)jumlah pasangannya.fmt.Printlnmencetak map dengan key yang diurutkan, bukan urutan kamu menulisnya.- Map kosong yang siap diisi:
make(map[string]int)ataumap[string]int{}.
Tambah, ubah, hapus
harga["Es jeruk"] = 6000 // key baru: ditambahkan
harga["Es teh"] = 4000 // key yang sudah ada: value-nya diganti
delete(harga, "Mie ayam") // dihapus
delete(harga, "Soto") // key-nya gak ada: gak terjadi apa-apa
fmt.Println(harga, len(harga))
map[Bakso urat:15000 Es jeruk:6000 Es teh:4000] 3
Menambah dan mengubah ditulis sama persis. Satu key cuma muncul sekali di map, jadi menulis ke key yang sudah ada berarti menggantinya.
Key yang gak ada: zero value dan comma-ok
fmt.Println(harga["Soto"]) // 0
h, ada := harga["Soto"]
fmt.Println(h, ada) // 0 false
h, ada = harga["Bakso urat"]
fmt.Println(h, ada) // 15000 true
- Membaca key yang gak ada gak bikin error. Hasilnya zero value dari tipe value-nya:
0untuk int,""untuk string,falseuntuk bool. Itu jawaban tebakannya:0. - Masalahnya,
0bisa juga harga yang memang 0. Untuk membedakannya, ambil dua nilai sekaligus. Nilai kedua (ada, sering dinamaiok) bernilaitruekalau key-nya ada. Pola ini disebut comma-ok. - Jadi untuk
m := map[string]int{"a": 1},val, ok := m["b"]membuatfmt.Println(val, ok)mencetak0 false. - Pola yang sering dipakai:
if h, ok := harga["Soto"]; !ok { fmt.Println("Soto gak ada di menu") }.
range di map: urutannya gak tetap
for nama, h := range harga {
fmt.Println(nama, h)
}
Jalankan dua kali, urutannya bisa beda:
Bakso urat 15000
Es teh 4000
Es jeruk 6000
Es teh 4000
Es jeruk 6000
Bakso urat 15000
Go sengaja gak menjamin urutan range di map, jadi jangan bergantung padanya. Butuh urutan tetap? Urutkan key-nya dulu: for _, nama := range slices.Sorted(maps.Keys(harga)) (Go 1.23 ke atas, dengan import "maps" dan "slices").
Menghitung dengan map
Karena key yang belum ada terbaca 0, jumlah[p]++ langsung bisa dipakai untuk menghitung, tanpa mengisi apa-apa dulu:
pesanan := []string{"Bakso urat", "Es teh", "Bakso urat", "Mie ayam", "Bakso urat", "Es teh"}
jumlah := make(map[string]int)
for _, p := range pesanan {
jumlah[p]++
}
fmt.Println(jumlah) // map[Bakso urat:3 Es teh:2 Mie ayam:1]
fmt.Println(len(jumlah)) // 3
p |
jumlah[p] sebelum |
sesudah |
|---|---|---|
| Bakso urat | 0 | 1 |
| Es teh | 0 | 1 |
| Bakso urat | 1 | 2 |
| Mie ayam | 0 | 1 |
| Bakso urat | 2 | 3 |
| Es teh | 1 | 2 |
Teks yang dipisah spasi bisa dihitung dengan cara yang sama: pecah dulu jadi slice dengan strings.Split(teks, " "), lalu range hasilnya. Jangan lupa import "strings"; tanpa itu Go menolak dengan undefined: strings. len(jumlah) memberi jumlah key yang berbeda.
Map nil: bisa dibaca, gak bisa ditulis
var harga map[string]int // belum dibuat: nil
fmt.Println(harga["Bakso urat"]) // 0, membaca aman
harga["Bakso urat"] = 15000 // panic
0
panic: assignment to entry in nil map
goroutine 1 [running]:
main.main()
/app/main.go:8 +0x85
exit status 2
var harga map[string]intcuma mendeklarasikan variabelnya; map-nya sendiri belum ada (nil). Membaca,len, danrangeaman dan hasilnya kosong, tapi menulis bikin panic.- Bikin dulu sebelum diisi:
harga := make(map[string]int)atauharga := map[string]int{}.new(map[string]int)gak membantu, karena itu cuma penunjuk ke map yang tetap nil.
📌 Map dan goroutine
Map bawaan gak aman ditulis dari beberapa goroutine sekaligus: Go menghentikan programnya dengan fatal error: concurrent map writes. Cara mengamankannya ada di lesson Mutex & Sync.
⚠️ Jebakan yang sering ketemu
- Menulis ke map nil.
var m map[string]intlalum["x"] = 1bikin panic. Bikin dulu denganmakeatau literal. - Mengira 0 artinya key-nya gak ada. Pakai comma-ok:
h, ok := harga[k]. - Bergantung pada urutan
range. Urutkan key-nya kalau butuh urutan tetap. - Lupa
import "strings"saat memakaistrings.Split.
TL;DR: map[string]int{"Bakso urat": 15000} menyimpan pasangan key dan value. m[k] membaca, m[k] = v menambah atau mengganti, delete(m, k) menghapus, len(m) menghitung pasangan. Key yang gak ada terbaca sebagai zero value (0), dan v, ok := m[k] memberi ok = false untuk membedakannya. Urutan range gak tetap, sedangkan fmt.Println mencetak key terurut. Map nil (var m map[string]int) bisa dibaca tapi panic saat ditulis, jadi bikin dulu dengan make(map[string]int) atau map[string]int{}. m[k]++ adalah cara singkat menghitung kemunculan.