Go, conosciuto anche come Golang, è un linguaggio di programmazione che combina semplicità, efficienza e potenza. Uno dei costrutti più utili e versatili in Go è il range, che permette di iterare su collezioni di dati come array, slice, map e stringhe. In questo articolo, esploreremo come funziona il range, come si utilizza e alcuni esempi pratici per sfruttarlo al meglio.

1. Cos’è il Range?

Il range è una parola chiave in Go che viene utilizzata per iterare su elementi di strutture dati come array, slice, map, stringhe e canali. Fornisce un modo semplice ed elegante per accedere a ciascun elemento di una collezione senza dover gestire manualmente gli indici o i contatori.

1.1. Sintassi di Base

La sintassi generale del range è la seguente:

for indice, valore := range collezione {
    // Codice da eseguire
}

Dove:

  • indice: La posizione corrente nell’iterazione (opzionale, a seconda della collezione).
  • valore: L’elemento corrente della collezione.
  • collezione: La struttura dati su cui si sta iterando (array, slice, map, stringa, ecc.).

2. Utilizzo del Range con Diverse Strutture Dati

Il range può essere utilizzato con diverse strutture dati in Go. Vediamo come funziona in ciascun caso.

2.1. Range con Array e Slice

Quando si utilizza il range con array o slice, restituisce sia l’indice che il valore dell’elemento corrente.

numeri := []int{10, 20, 30, 40, 50}

for indice, valore := range numeri {
    fmt.Printf("Indice: %d, Valore: %d\n", indice, valore)
}

Output:

Indice: 0, Valore: 10
Indice: 1, Valore: 20
Indice: 2, Valore: 30
Indice: 3, Valore: 40
Indice: 4, Valore: 50

Se non ti interessa l’indice, puoi ignorarlo usando _:

for _, valore := range numeri {
    fmt.Println(valore)
}

2.2. Range con Map

Quando si utilizza il range con una map, restituisce sia la chiave che il valore associato.

mappa := map[string]int{
    "uno": 1,
    "due": 2,
    "tre": 3,
}

for chiave, valore := range mappa {
    fmt.Printf("Chiave: %s, Valore: %d\n", chiave, valore)
}

Output (l’ordine non è garantito):

Chiave: uno, Valore: 1
Chiave: due, Valore: 2
Chiave: tre, Valore: 3

Anche in questo caso, se non ti interessa la chiave o il valore, puoi ignorarli usando _.

2.3. Range con Stringhe

Quando si utilizza il range con una stringa, itera sui caratteri della stringa, restituendo l’indice e il valore Unicode del carattere corrente.

testo := "Ciao"

for indice, carattere := range testo {
    fmt.Printf("Indice: %d, Carattere: %c\n", indice, carattere)
}

Output:

Indice: 0, Carattere: C
Indice: 1, Carattere: i
Indice: 2, Carattere: a
Indice: 3, Carattere: o

Nota: Go gestisce automaticamente i caratteri Unicode, quindi il range è particolarmente utile per lavorare con stringhe multilingue.

2.4. Range con Canali

Il range può essere utilizzato anche con i canali per iterare sui valori inviati attraverso il canale fino a quando questo non viene chiuso.

ch := make(chan int)

go func() {
    ch <- 1
    ch <- 2
    ch <- 3
    close(ch)
}()

for valore := range ch {
    fmt.Println(valore)
}

Output:

1
2
3

Il ciclo si interrompe automaticamente quando il canale viene chiuso.

3. Esempi Pratici

Vediamo alcuni esempi pratici per capire come il range può semplificare il codice.

3.1. Somma degli Elementi di una Slice

Puoi usare il range per calcolare la somma degli elementi di una slice:

numeri := []int{10, 20, 30, 40, 50}
somma := 0

for _, valore := range numeri {
    somma += valore
}

fmt.Println("Somma:", somma)

Output:

Somma: 150

3.2. Contare le Occorrenze in una Stringa

Puoi usare il range per contare quante volte un carattere appare in una stringa:

testo := "banana"
conteggio := make(map[rune]int)

for _, carattere := range testo {
    conteggio[carattere]++
}

fmt.Println(conteggio)

Output:

map[97:3 98:1 110:2]

Dove 97, 98 e 110 sono i valori Unicode dei caratteri a, b e n rispettivamente.

3.3. Filtrare Elementi in una Slice

Puoi usare il range per filtrare elementi in una slice:

numeri := []int{1, 2, 3, 4, 5, 6}
pari := []int{}

for _, valore := range numeri {
    if valore%2 == 0 {
        pari = append(pari, valore)
    }
}

fmt.Println("Numeri pari:", pari)

Output:

Numeri pari: [2 4 6]

4. Conclusioni

Il range è uno strumento potente e versatile in Go che semplifica l’iterazione su array, slice, map, stringhe e canali. Grazie alla sua sintassi chiara e intuitiva, ti permette di scrivere codice più conciso e leggibile. Con questa guida, hai ora una solida base per utilizzare il range nei tuoi progetti Go e sfruttarne al massimo le potenzialità.