Map — Go

Map di Go Map adalah struktur data key-value seperti dictionary di Python atau object di JavaScript. Membuat Map // Literal umur := map[string]int{ "Budi"…

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 jeruk gak ada di daftar harga. fmt.Println(harga["Es jeruk"]) hasilnya apa: error, nil, atau 0? 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

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

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

📌 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

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.

Yang akan kamu pelajari