Strutture Dati
Sebbene Go abbia una sintassi semplice, include diverse potenti strutture dati core. Queste strutture sono i mattoni fondamentali dei programmi Go e comprendere i loro principi di implementazione aiuta a scrivere codice più efficiente. Questo articolo presenta alcune delle strutture dati più comunemente usate in Go e le loro implementazioni sottostanti.
Strutture Dati di Base
slice Slice
Le slice sono la struttura dati più comunemente usata in Go, un'astrazione e incapsulamento degli array. Caratteristiche principali:
- Dimensione Dinamica: la lunghezza delle slice può crescere dinamicamente
- Semantica di Riferimento: quando una slice viene passata, viene copiata solo la struttura, non l'array sottostante
- Meccanismo di Espansione: quando la capacità è insufficiente, si espande automaticamente
Le slice sono rappresentate a runtime dalla struttura slice, che contiene un puntatore all'array sottostante, la lunghezza e la capacità.
string Stringhe
Le stringhe sono uno dei tipi di dati più fondamentali in Go. Caratteristiche principali:
- Immutabilità: una volta creata, una stringa non può essere modificata
- Codifica UTF-8: generalmente rappresentano testo codificato in UTF-8
- Sicurezza del Valore Zero: il valore zero di una stringa è la stringa vuota
"", nonnil
Le stringhe sono rappresentate a runtime dalla struttura stringStruct, che contiene un puntatore a un array di byte e la lunghezza.
Strutture Dati Container
map Mappe
Le map sono contenitori chiave-valore built-in in Go, implementati come tabelle hash. Caratteristiche principali:
- Implementazione Hash Table: posiziona rapidamente gli elementi tramite funzioni hash
- Espansione Automatica: si espande automaticamente quando il fattore di carico è troppo alto
- Non Concurrent-Safe: la lettura/scrittura concorrente richiede meccanismi di sincronizzazione aggiuntivi
Le map sono rappresentate a runtime dalla struttura hmap, che contiene l'array di bucket, il seed hash, il conteggio degli elementi e altri campi.
syncmap Mappe Concorrenti
sync.Map è una mappa thread-safe fornita dalla libreria standard, adatta per scenari con molte letture e poche scritture. Caratteristiche principali:
- Separazione Lettura/Scrittura: usa due map, read e dirty, per separare letture e scritture
- Operazioni Atomiche: la read map usa operazioni atomiche, senza bisogno di lock
- Migrazione Graduale: quando il conteggio miss raggiunge la soglia, la dirty diventa la read
sync.Map scambia spazio per tempo, offrendo prestazioni migliori rispetto a map + mutex in scenari specifici.
Strutture Dati Concorrenti
channel Canali
I channel sono il rappresentante tipico del paradigma CSP di Go, usati per la comunicazione tra goroutine. Caratteristiche principali:
- Comunicazione tra Goroutine: passaggio di dati tra goroutine tramite channel
- Meccanismo di Sincronizzazione: i channel senza buffer possono essere usati per sincronizzare goroutine
- Coda con Lock: sottostante è una coda circolare con lock
I channel sono rappresentati a runtime dalla struttura hchan, che contiene un buffer circolare, code di attesa e altri campi.
select Multiplexing
select può monitorare lo stato di più channel simultaneamente, implementando il multiplexing. Caratteristiche principali:
- Non Bloccante: può controllare in modo non bloccante se più channel sono disponibili
- Selezione Casuale: quando più channel sono disponibili, ne seleziona uno casualmente per l'esecuzione
- Controllo Timeout: può essere usato con
time.Afterper implementare meccanismi di timeout
select è rappresentato a runtime dalla struttura scase per ogni branch, controllando lo stato dei channel tramite un meccanismo di polling.
Suggerimenti per l'Apprendimento
Si consiglia di seguire questo ordine di apprendimento:
- Iniziare con slice Slice e string Stringhe per comprendere le strutture dati di base
- Proseguire con map Mappe per capire l'implementazione delle tabelle hash
- Poi studiare channel Canali per comprendere il meccanismo di comunicazione tra goroutine
- Quindi apprendere select Multiplexing per padroneggiare le tecniche di multiplexing
- Infine studiare syncmap Mappe Concorrenti per capire l'implementazione thread-safe
