Map menyimpan pasangan kunci-nilai, tetapi operasi sehari-hari di sekitarnya — mengkloning, menyalin, menyaring, membandingkan, sampai mengiterasi secara terurut — lama ditulis manual dengan loop sendiri. Sejak Go 1.21, package maps menyediakan seluruh utilitas tersebut secara generik untuk map tipe apa pun. Chapter ini membedah fungsi intinya sekaligus menjelaskan perilaku iterasi map yang harus diketahui setiap penulis Go.

Keys dan Values sebagai Iterator #

Sejak Go 1.23, maps.Keys dan maps.Values tidak lagi mengembalikan slice. Keduanya mengembalikan iterator bertipe iter.Seq yang dapat dipakai langsung pada for range, atau diteruskan ke fungsi penerima iterator seperti slices.Collect dan slices.Sorted. Untuk mengiterasi map dengan urutan kunci yang pasti, idiomnya menggabungkan keduanya:

go
	for _, k := range slices.Sorted(maps.Keys(stok)) {
		fmt.Println(k, stok[k])
	}

maps.Keys(stok) menghasilkan iterator kunci, slices.Sorted mengurutkannya menjadi slice baru, dan loop membaca nilai lewat stok[k]. Tanpa pengurutan, loop for k := range stok tetap sah — hanya saja urutannya tidak bisa diandalkan. slices.Collect(maps.Keys(m)) mengumpulkan kunci menjadi slice tanpa mengurutkan, berguna bila urutan tidak penting.

Iterator nilai dibaca dengan satu variabel loop karena maps.Values mengalirkan nilai saja:

go
	for v := range maps.Values(stok) {
		fmt.Println(v)

Clone dan Copy #

maps.Clone menyalin seluruh map menjadi map baru dengan tipe sama. Penambahan atau penghapusan pada salinan tidak menyentuh map asli, sehingga fungsi yang perlu memodifikasi data dapat bekerja pada salinan. maps.Copy memindahkan pasangan kunci-nilai dari map sumber ke map target: pasangan yang kuncinya sudah ada di target akan ditimpa nilainya, kunci yang belum ada akan ditambahkan.

Sebutan singkat: maps.Collect membangun map baru dari iterator pasangan, dan maps.Insert mengisi map dari iterator pasangan — keduanya berguna saat data berpindah antar bentuk iterator dan map.

DeleteFunc untuk Menyaring #

maps.DeleteFunc menghapus setiap pasangan yang membuat predikat bernilai true. Predikatnya menerima kunci dan nilai, jadi penyaringan bisa mempertimbangkan keduanya — misalnya menghapus item stok di bawah batas minimum. Fungsi memodifikasi map di tempat dan tidak mengembalikan map baru.

Equal dan EqualFunc #

maps.Equal membandingkan dua map secara pasangan: sama-sama tidak punya kunci lebih, dan setiap kunci yang sama nilainya harus sama. Perbandingan dengan operator == pada dua variabel map hanya memeriksa apakah keduanya merujuk map yang sama, bukan isinya. maps.EqualFunc memakai fungsi pembanding nilai sendiri, berguna untuk nilai yang tidak comparable seperti slice.

Program Utuh #

Berkas maps-demo.go merangkai seluruh materi chapter:

go
package main

import (
	"fmt"
	"maps"
	"slices"
)

func main() {
	stok := map[string]int{
		"pensil":    24,
		"buku":      12,
		"penghapus": 7,
	}

	// Urutan iterasi map diacak Go; urutkan kuncinya agar output selalu sama.
	for _, nama := range slices.Sorted(maps.Keys(stok)) {
		fmt.Printf("%-9s : %d\n", nama, stok[nama])
	}

	// Clone menyalin seluruh map menjadi map baru yang mandiri.
	salinan := maps.Clone(stok)
	salinan["spidol"] = 3
	fmt.Println("kunci    :", len(salinan), "disalin,", len(stok), "asli")

	// Copy memindahkan pasangan kunci-nilai dari sumber ke target.
	target := map[string]int{"buku": 99}
	maps.Copy(target, stok)
	fmt.Println("copy     :", target)

	// DeleteFunc menghapus pasangan yang memenuhi predikat.
	sisa := maps.Clone(stok)
	maps.DeleteFunc(sisa, func(k string, v int) bool {
		return v < 10
	})
	fmt.Println("sisa     :", sisa)

	// Equal membandingkan isi dua map pasangan demi pasangan.
	fmt.Println("equal    :", maps.Equal(stok, maps.Clone(stok)), maps.Equal(stok, sisa))

	// Values mengembalikan iterator nilai (satu variabel loop) untuk dijumlahkan.
	total := 0
	for v := range maps.Values(stok) {
		total += v
	}
	fmt.Println("total    :", total)
}

Jalankan program dari folder chapter:

bash
go run maps-demo.go

Output yang Dihasilkan:

text
buku      : 12
penghapus : 7
pensil    : 24
kunci    : 4 disalin, 3 asli
copy     : map[buku:12 penghapus:7 pensil:24]
sisa     : map[buku:12 pensil:24]
equal    : true false
total    : 43

Mari kita telaah baris demi baris program di atas:

  1. Baris 4-6: tiga package diimpor — fmt untuk mencetak, maps untuk utilitas map, dan slices untuk Sorted.
  2. Baris 10-14: map stok dideklarasikan dengan tiga pasangan kunci-nilai.
  3. Baris 17-19: kunci diurutkan lewat slices.Sorted(maps.Keys(stok)) sehingga tiga baris pertama output selalu buku, penghapus, lalu pensil.
  4. Baris 22-24: Clone membuat salinan; penambahan spidol hanya menaikkan jumlah kunci salinan menjadi 4.
  5. Baris 27-29: Copy menimpa nilai buku di target dengan nilai dari sumber dan menambahkan dua kunci lain.
  6. Baris 32-36: DeleteFunc menghapus pasangan dengan nilai di bawah 10, menyisakan buku dan pensil.
  7. Baris 39: Equal membandingkan stok dengan klonnya (sama) dan dengan sisa (berbeda).
  8. Baris 42-46: iterator maps.Values dijumlahkan menjadi total 43 lewat satu variabel loop.

Referensi #

Map dan slice kini bisa diolah dengan utilitas standar yang ringkas. Perhatian kita beralih ke jejak eksekusi program: dua chapter berikutnya membahas pencatatan kejadian dengan log klasik dan log/slog terstruktur.

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

maps-demo.go

Unduh berkas
go
package main

import (
	"fmt"
	"maps"
	"slices"
)

func main() {
	stok := map[string]int{
		"pensil":    24,
		"buku":      12,
		"penghapus": 7,
	}

	// Urutan iterasi map diacak Go; urutkan kuncinya agar output selalu sama.
	for _, nama := range slices.Sorted(maps.Keys(stok)) {
		fmt.Printf("%-9s : %d\n", nama, stok[nama])
	}

	// Clone menyalin seluruh map menjadi map baru yang mandiri.
	salinan := maps.Clone(stok)
	salinan["spidol"] = 3
	fmt.Println("kunci    :", len(salinan), "disalin,", len(stok), "asli")

	// Copy memindahkan pasangan kunci-nilai dari sumber ke target.
	target := map[string]int{"buku": 99}
	maps.Copy(target, stok)
	fmt.Println("copy     :", target)

	// DeleteFunc menghapus pasangan yang memenuhi predikat.
	sisa := maps.Clone(stok)
	maps.DeleteFunc(sisa, func(k string, v int) bool {
		return v < 10
	})
	fmt.Println("sisa     :", sisa)

	// Equal membandingkan isi dua map pasangan demi pasangan.
	fmt.Println("equal    :", maps.Equal(stok, maps.Clone(stok)), maps.Equal(stok, sisa))

	// Values mengembalikan iterator nilai (satu variabel loop) untuk dijumlahkan.
	total := 0
	for v := range maps.Values(stok) {
		total += v
	}
	fmt.Println("total    :", total)
}