Uno switch confronta un valore con un elenco di casi ed esegue la prima corrispondenza. A differenza di C, Java e JavaScript, un caso in Go non prosegue nel successivo, quindi non c'è nessun break da dimenticare.
I casi vengono controllati dall'alto verso il basso, e viene eseguito solo il primo che corrisponde. default viene eseguito quando nulla corrisponde; è facoltativo e può stare in qualsiasi punto dell'elenco, anche se per convenzione va per ultimo.
Più valori per caso
case "sat", "sun": corrisponde a uno qualsiasi dei due valori. È così che Go esprime ciò che il C fa con i casi vuoti impilati. Funziona con qualsiasi tipo confrontabile: stringhe, numeri, rune, booleani, puntatori e tipi con nome come gli enum:
Due casi con lo stesso valore costante sono un errore di compilazione:
./main.go:10:7: duplicate case 1 (constant of type int) in expression switch
./main.go:8:7: previous case
switch senza condizione
Ometti l'espressione e ogni caso diventa un test booleano. È la forma più pulita che Go offre per una lunga catena if/else if:
switch { è un'abbreviazione di switch true {. Dato che vince il primo caso vero, l'ordine conta: bmi < 25 viene raggiunto solo quando bmi < 18.5 era falso, quindi ogni caso può dare per scontato che quelli sopra siano falliti.
switch con istruzione di inizializzazione
Come if, anche uno switch può iniziare con una breve istruzione. Le variabili dichiarate lì sono visibili solo dentro lo switch:
L'istruzione di inizializzazione si può combinare anche con uno switch senza condizione: switch n := len(items); { case n == 0: ... }.
fallthrough
Quando vuoi davvero continuare nel caso successivo, scrivi fallthrough come ultima istruzione di un caso. Passa il controllo al corpo del caso successivo senza valutarne la condizione:
Il livello 2 stampa write e poi read, accumulando i permessi verso il basso. Le condizioni dei casi successivi non vengono controllate: dopo il fallthrough da case 2, case 1 viene eseguito anche se level vale 2.
Regole per fallthrough:
- Deve essere l'ultima istruzione del caso.
- Non può comparire nell'ultimo caso:
cannot fallthrough final case in switch. - Non è ammesso in un type switch.
In pratica fallthrough è raro nel codice Go. I valori multipli per caso coprono l'esigenza comune, e chiamate esplicite a funzioni sono di solito più chiare di una catena di fallthrough.
break in uno switch
break dentro un caso esce dallo switch. I casi finiscono da soli, quindi ti serve solo per uscire in anticipo da un caso. La trappola è uno switch dentro un ciclo:
Senza l'etichetta loop, break termina lo switch e il ciclo prosegue fino a "c". continue, invece, si riferisce sempre al ciclo che lo contiene, perché uno switch non è un ciclo.
switch sui tipi
Un type switch si dirama in base al tipo dinamico di un valore interfaccia, usando la forma speciale v.(type):
In un caso con un solo tipo, x ha quel tipo (len(x) funziona nel caso string). In un caso che elenca più tipi, x mantiene il tipo interfaccia. La pagina sulle type assertion tratta in dettaglio i type switch e l'asserzione v.(T).
Cosa fa diversamente lo switch di Go
| Comportamento | C, Java, JavaScript | Go |
|---|---|---|
| Proseguire nel caso successivo | per default | solo con fallthrough |
break alla fine di ogni caso | obbligatorio | non serve |
| Più valori per caso | casi vuoti impilati | case a, b, c: |
| Valori dei casi | costanti (quasi sempre) | qualsiasi espressione, valutata dall'alto verso il basso |
| Valore dello switch | tipi interi (C) | qualsiasi tipo confrontabile |
| Nessuna espressione nello switch | non ammesso | switch { case cond: } |
Le espressioni dei casi non devono essere per forza costanti. case limit(), max + 1: è valido; vengono valutate in ordine finché una non corrisponde, quindi le espressioni successive potrebbero non essere mai eseguite.
Esaustività
Go non controlla che uno switch su un enum copra ogni valore. Aggiungi un default che registra un log, restituisce un errore o va in panic per i valori che non ti aspettavi, oppure usa il linter exhaustive (parte di golangci-lint) per farti segnalare i casi mancanti in fase di build.
Domande frequenti
In Go lo switch prosegue nel caso successivo?
No. Un caso in Go termina automaticamente al case successivo; non scrivi mai break per fermarlo. Se vuoi che l'esecuzione continui nel corpo del caso successivo, scrivi fallthrough come ultima istruzione del caso. Salta in modo incondizionato, senza controllare la condizione del caso successivo.
Come confronto più valori in un solo caso in Go?
Elencali separati da virgole: case "sat", "sun":. Il caso viene eseguito se il valore dello switch è uguale a uno qualsiasi di essi. Questo sostituisce i casi vuoti impilati che useresti in C o Java.
Cos'è uno switch senza condizione in Go?
switch { case x < 0: ...; case x == 0: ...; default: ... }. Senza un'espressione dopo switch, ogni caso è una condizione booleana e viene eseguito il primo vero. È il sostituto idiomatico di una lunga catena if/else if.
Cosa fa break dentro uno switch in Go?
Termina lo switch, non un ciclo for che lo contiene. Serve raramente, perché i casi finiscono da soli, ma sorprende chi scrive break in uno switch dentro un ciclo aspettandosi di uscire dal ciclo. Per quello usa un break con etichetta oppure return.