Goto in Go
L’istruzione goto in Go permette di saltare incondizionatamente a un’etichetta all’interno della stessa funzione. È una funzionalità presente ma raramente utilizzata nel codice Go idiomatico.
Sintassi Base
func main() {
fmt.Println("Inizio")
goto fine
fmt.Println("Questo non viene eseguito")
fine:
fmt.Println("Fine")
}
// Output:
// Inizio
// Fine
Dichiarazione di Etichette
Le etichette sono identificatori seguiti da due punti (:):
func esempio() {
i := 0
ripeti:
if i < 5 {
fmt.Println(i)
i++
goto ripeti
}
}
Restrizioni
Go impone restrizioni importanti su goto per garantire la sicurezza del codice:
Non può saltare oltre dichiarazioni di variabili
// ERRORE: goto salta oltre la dichiarazione di x
goto dopo
x := 10
dopo:
fmt.Println("dopo")
Non può entrare in un blocco dall’esterno
// ERRORE: non può saltare dentro un blocco if/for
goto dentro
if true {
dentro:
fmt.Println("dentro")
}
Deve rimanere nella stessa funzione
Non è possibile usare goto per saltare tra funzioni diverse.
Casi d’Uso Legittimi
Uscita da Loop Annidati
Questo è il caso più comune e accettato:
func cercaMatrice(matrice [][]int, obiettivo int) (int, int) {
for i, riga := range matrice {
for j, valore := range riga {
if valore == obiettivo {
goto trovato
}
}
}
return -1, -1
trovato:
return i, j
}
Tuttavia, in Go è preferibile usare etichette con break:
func cercaMatrice(matrice [][]int, obiettivo int) (int, int) {
esterno:
for i, riga := range matrice {
for j, valore := range riga {
if valore == obiettivo {
break esterno
}
}
}
}
Pattern di Cleanup
func elabora() error {
risorsa1, err := apriRisorsa1()
if err != nil {
goto cleanup
}
risorsa2, err := apriRisorsa2()
if err != nil {
goto cleanup1
}
return nil
cleanup1:
risorsa1.Chiudi()
cleanup:
return err
}
Nota: In Go idiomatico, questo pattern è meglio gestito con defer.
Perché Evitare goto
- Rende il flusso del codice difficile da seguire
- Go offre alternative migliori:
breakcon etichette,defer, funzioni - Il codice con
gotoè più difficile da mantenere e testare
Conclusione
Sebbene goto sia disponibile in Go, il suo uso è fortemente sconsigliato nella maggior parte dei casi. Go fornisce alternative più chiare come break e continue con etichette, defer per il cleanup e funzioni per organizzare il codice. Usa goto solo quando le alternative risultano significativamente più complesse.