Il
goto non e' il
diavolo, ovviamente.
Generalmente non serve, visto che le strutture di controllo sono adeguate nella maggior parte delle occasioni.
Quando
potrebbe servire, spesso la stessa cosa puo' essere fatta usando gli statement
continue <label> e
break <label>.
Ad esempio:
Codice:
...
loop: while(<condizione 1>)
{
...while(<condizione 2>)
...{
......if (<condizione 3>) continue loop;
...
......if (<condizione 4>) break loop;
...}
}
....
Il seguente codice dice:
1) ho due loop nidificati.
2) all'interno del secondo loop, se capita la <condizione 3>, devo continuare ricominciando direttamente dal loop piu' esterno
3) se capita la <condizione 4>, devo uscire da ENTRAMBI i loop.
E' ovvio che ci sono n-mila modi per fare la stessa cosa senza usare la label (uso di flag, aggiunta di if e di condizioni sui flag, ...)
L'unico inconveniente e' che
break e
continue possono essere utilizzati solo all'interno di cicli (for/while/...).
C'e' un caso in cui il
goto risulta utile, ed e' il seguente:
supponiamo di avere un codice di questo tipo:
Codice:
...
if(<condizione 1>)
{
....azione_1
....if(<condizione 2>)
....{
........azione_2
........if(<condizione 3>)
........{
............azione_3
............if(<condizione 4>)
............{
................azione_4
................ <altri test>
............}
........}
....}
...
azione_finale
Ora, finche' ci sono 2 o 3 condizioni, piu' o meno il codice risulta leggibile, ma se le condizioni iniziano ad essere 4 o piu', il codice comincia ad essere complicato da leggere perche' potrebbe uscire dallo schermo (non si dovrebbe mai scrivere righe piu' lunghe di 80/132 caratteri, per mantenere la leggibilita').
La soluzione semplice e' inverire i test ed usare il
goto
Codice:
...
if( ! <condizione 1>)
goto esci;
azione_1
if( ! <condizione 2>)
goto esci;
azione_2
if( ! <condizione 3>)
goto esci;
azione_3
if( ! <condizione 4>)
goto esci;
azione_4
esci:
azione_finale
...
In questo modo, il codice risulta avere una struttura lineare e risulta evidente la presenza di uscite multiple.
Se non dovesse esistere
azione_finale, allora al posto del
goto si puo' usare direttamente un
return
Un'altro caso e' il seguente:
Codice:
...
if(<condizione 1>) then goto exit_1
azione_1
if(<condizione 2>) then goto exit_2
azione_2
if(<condizione 3>) then goto exit_3
azione_3
...
exit_3:
.... azione_finale_3
exit_2:
.... azione_finale_2
exit_1:
.... azione_finale_1
azione_finale
Qui, a seconda di una certa condizione, deve essere fatto un certo numero di azioni finali.
Ovviamente, anche in questo caso si puo' fare la stessa cosa con un opportuno numero di flag e di if, ma probabilmente il codice risultante risulterebbe PIU' complicato dell'uso del
goto.
In soldoni:
l'assioma e'
scrivere codice comprensibile.
Se l'uso del
goto migliora la comprensibilita' del codice, allora vale la pena usarlo.