map și map-uri în Go

Tabel cheie-valoare (dicționar): căutare rapidă după cheie, adăugare, ștergere și verificare cu v, ok.

Sintaxă
m := map[string]int{"Ana": 9}
m := make(map[string]int)
m[cheie] = valoare
v := m[cheie]
v, ok := m[cheie]
delete(m, cheie)

Ce face map și map-uri

Un map (map[K]V) leagă chei de tip K de valori de tip V: map[string]int leagă texte de numere. Cheia poate fi orice tip comparabil cu == (numere, texte, struct-uri simple, array-uri), dar nu un slice, un map sau o funcție. Map-ul se creează cu un literal sau cu make.

m[k] = v adaugă sau înlocuiește. m[k] dă valoarea, iar pentru o cheie inexistentă dă valoarea zero a tipului. Ca să afli dacă cheia există, folosește forma cu două valori: v, ok := m[k]. delete(m, k) șterge o cheie, len(m) dă numărul de perechi, iar clear(m) le șterge pe toate.

Ordinea parcurgerii cu range este aleatorie. fmt.Println afișează însă un map cu cheile sortate. Un map nu este sigur pentru scrieri din mai multe goroutine fără sync.Mutex. Map-urile sunt referințe: o funcție care primește un map îl poate modifica.

Exemple

Exemplul 1: Operațiile de bază

package main

import "fmt"

func main() {
    note := map[string]int{"Ana": 9, "Mihai": 7}
    note["Ioana"] = 10 // adăugare
    note["Mihai"] = 8  // modificare
    fmt.Println(note, "perechi:", len(note))

    if n, ok := note["Radu"]; ok {
        fmt.Println("Radu are", n)
    } else {
        fmt.Println("Radu nu are notă; m[\"Radu\"] =", note["Radu"])
    }

    delete(note, "Ana")
    fmt.Println(note)
}

Rezultat

map[Ana:9 Ioana:10 Mihai:8] perechi: 3
Radu nu are notă; m["Radu"] = 0
map[Ioana:10 Mihai:8]

Exemplul 2: Numărarea cuvintelor

frecventa[c]++ merge și pentru cuvinte noi, pentru că pornesc de la 0. Cheile sunt sortate pentru o afișare stabilă.

package main

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

func main() {
    text := "ana are mere ana are pere ana"
    frecventa := make(map[string]int)
    for _, c := range strings.Fields(text) {
        frecventa[c]++
    }
    for _, c := range slices.Sorted(maps.Keys(frecventa)) {
        fmt.Printf("%-5s %d\n", c, frecventa[c])
    }
}

Rezultat

ana   3
are   2
mere  1
pere  1

Exemplul 3: Map cu valori slice și struct ca cheie

package main

import "fmt"

type Punct struct{ X, Y int }

func main() {
    pePrieteni := map[string][]string{}
    pePrieteni["Ana"] = append(pePrieteni["Ana"], "Ioana", "Radu")
    pePrieteni["Mihai"] = append(pePrieteni["Mihai"], "Ana")
    fmt.Println(pePrieteni)

    harta := map[Punct]string{{0, 0}: "start", {3, 4}: "comoară"}
    fmt.Println(harta[Punct{3, 4}])
}

Rezultat

map[Ana:[Ioana Radu] Mihai:[Ana]]
comoară

Greșeli frecvente

  • Scrierea într-un map nil: panic: assignment to entry in nil map.
  • Bazarea pe ordinea din for range: este diferită la fiecare rulare.
  • Modificarea unui câmp de struct direct în map: m[k].Nota = 10 dă cannot assign to struct field m[k].Nota in map. Citește valoarea, modific-o și pune-o înapoi, sau folosește map[K]*T.
  • Scrieri din mai multe goroutine fără sincronizare: fatal error: concurrent map writes.

Comenzi înrudite

  • delete: Șterge o cheie (și valoarea ei) dintr-un map; dacă cheia nu există sau map-ul este nil, nu face nimic.
  • clear: Golește un map (șterge toate cheile) sau pune pe zero toate elementele unui slice, păstrând lungimea.
  • make: Creează și inițializează slice-uri, map-uri și canale, cu lungime, capacitate sau buffer dat.
  • range: Parcurge într-un for elementele unui slice, array, map, text, canal, număr sau iterator.
  • struct și struct-uri: Grupează mai multe câmpuri cu nume și tipuri diferite într-un singur tip; baza pentru modelarea datelor în Go.