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": 25,
"Sari": 30,
"Andi": 22,
}
// Menggunakan make
skor := make(map[string]int)
Operasi Map
m := map[string]int{"a": 1, "b": 2}
// Akses
fmt.Println(m["a"]) // 1
// Set / Update
m["c"] = 3
// Delete
delete(m, "b")
// Cek apakah key ada
val, ok := m["a"]
if ok {
fmt.Println("Ada:", val)
} else {
fmt.Println("Tidak ada")
}
Iterasi Map
for key, value := range m {
fmt.Printf("%s: %d\n", key, value)
}
Panjang Map
fmt.Println(len(m)) // jumlah key-value pairs
⚠️ Map Go TIDAK Thread-Safe
Ini salah satu jebakan terbesar dalam Go concurrency. Map bawaan Go tidak aman diakses dari banyak goroutine secara bersamaan — runtime Go akan crash program-mu (fatal error: concurrent map writes) jika mendeteksi read+write simultan.
// BAHAYA — race condition, program bisa crash
m := make(map[string]int)
for i := 0; i < 100; i++ {
go func(i int) {
m[fmt.Sprintf("k%d", i)] = i // panic!
}(i)
}
Solusi 1: sync.Mutex — paling umum dan fleksibel:
var mu sync.Mutex
m := make(map[string]int)
go func() {
mu.Lock()
defer mu.Unlock()
m["key"] = 42
}()
Solusi 2: sync.RWMutex — cocok kalau read jauh lebih sering dari write (banyak reader bisa lock bersamaan):
var mu sync.RWMutex
mu.RLock() // baca
val := m["key"]
mu.RUnlock()
mu.Lock() // tulis
m["key"] = 100
mu.Unlock()
Solusi 3: sync.Map — map bawaan yang thread-safe. Tapi hanya optimal untuk pola "write-once, read-many" (cache) atau key yang tumpang tindih jarang. Untuk kasus umum, Mutex + map lebih cepat.
Cara deteksi race condition: jalankan program dengan go run -race main.go. Race detector akan melaporkan akses tidak sinkron yang bisa jadi bug.