Vamos usar goto?
Autor: Renan Greinert | Publicado: 2011-09-01T19:12:00-07:00


Meu Deus! Isso é coisa do capeta!
Muito se fala mal do bom e velho goto. Os professores abominam seu uso, o Java não tem (embora o use indiretamente por meio dos breaks) e a maioria dos livros mandam você manter distância desta função. Até mesmo o velho Dijkstra escreveu um artigo intitulado "Go To Statement Considered Harmful", então se ele falou está falado, não é?
Mas não é bem assim. O ódio ao goto pode ser explicado por um contexto histórico. O bom e velho Assembly não possui if/then/else, while, for ou coisa do tipo. O Fortran, nos seus primórdios, também não possuía. Todos os laços e decisões do código eram feitos por meio de go tos. Assim, os primeiros programadores de C estavam acostumados com gotos e os utilizavam sem dó. Isso é um convite para transformar seu código em um belo dum espaguete, impossível de ser compreendido.  
Porém os tempos são outros. Usar gotos para decisões e laços é, sim, uma bela duma merda, mas existem situações em que o goto pode te ajudar a construir um código mais limpo.
Vamos ao exemplo:
Exemplo 1:

//Procurando Nemofor ( i = 0; i &lt; 1000; ++i ){&nbsp;&nbsp;&nbsp; for ( j = 0; j &lt; 1000; ++j )&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for ( k = 0; k &lt; 1000; ++k )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; //faz milhares de coisas aqui&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; if ( oceano[i][j][k] == NEMO )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; //Encontrei! Quero cair fora daqui!&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; }
}
Ok, você encontrou Nemo. E agora, como sair dessa?Se colocar um break, somente o laço do k será cortado. O restante continuará sendo executado.Outra solução seria marcar uma flag como nemoEncontrado = true dentro do if e verificar em cada for, mas não seria lá a solução mais bonita do mundo.E por que não colocar um goto aqui?

//Procurando Nemofor ( i = 0; i &lt; 1000; ++i ){&nbsp;&nbsp;&nbsp; for ( j = 0; j &lt; 1000; ++j )&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for ( k = 0; k &lt; 1000; ++k )&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //faz milhares de coisas aqui&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if ( oceano[i][j][k] == NEMO )&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //Encontrei! Quero cair fora daqui!&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; goto FimBuscaNemo;   &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; }
}FimBuscaNemo:…
Pronto, um bom uso do goto :)
Outro exemplo seria para funções com múltiplos retornos.É uma boa prática que cada função possua apenas 1 ponto de retorno, mas às vezes isso acarreta em um monte de ifs encadeados. Mais uma vez o goto pode te ajudar:
Exemplo 2:

int func(){&nbsp;&nbsp;&nbsp; AlocaUmMonteDeCoisaAqui();
&nbsp;&nbsp;&nbsp; if ( abrirArquivo() == false )
&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; DesalocaTudoQueAlocou();&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return ERRO_ABRIR_ARQUIVO;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; if ( arquivoVazio() == true )&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; DesalocaTudoQueAlocou();&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return ERRO_ARQUIVO_VAZIO;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; if ( checkSum() == false )&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; DesalocaTudoQueAlocou();&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return ERRO_CHECKSUM;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; if ( tamanhoArquivo() &lt; 100 )&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; DesalocaTudoQueAlocou();&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return ERRO_TAMANHO_INVALIDO;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; //faz um monte de coisa
&nbsp;&nbsp;&nbsp; DesalocaTudoQueAlocou();&nbsp;&nbsp;&nbsp; return BELEZA;
}
Este é um exemplo muito comum no dia a dia. A função aloca um monte de coisa no começo (poderia bloquear semáforos também) e para cada retorno precisa desalocar tudo. É também um erro muito comum um programador ir dar manutenção, colocar um novo return em algum ponto e esquecer de chamar a DesalocaTudoQueAlocou().
Uma função mais elegante e segura poderia ser escrita como:

int func(){&nbsp;&nbsp;&nbsp; int retval = BELEZA;
&nbsp;&nbsp;&nbsp; AlocaUmMonteDeCoisaAqui();
&nbsp;&nbsp;&nbsp; if ( abrirArquivo() == false )
&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; retval = ERRO_ABRIR_ARQUIVO;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; goto Fim_Func;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp;&nbsp;if ( arquivoVazio() == true )&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; retval = ERRO_ARQUIVO_VAZIO;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; goto Fim_Func;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; if ( checkSum() == false )&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; retval = ERRO_CHECKSUM;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; goto Fim_Func;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp;&nbsp;if ( tamanhoArquivo() &lt; 100 )&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; retval = ERRO_TAMANHO_INVALIDO;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; goto Fim_Func;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; //faz um monte de coisa
Fim_Func:
&nbsp;&nbsp;&nbsp; DesalocaTudoQueAlocou();&nbsp;&nbsp;&nbsp; return retval;
}
Aí está, outro uso saudável do goto!
Ou seja, não precisa ter medo da linguagem. Basta apenas usá-la corretamente.
Duas regras básicas devem ser seguidas quanto ao uso desta função:
1 – Só salte para linhas a frente da atual, e não para trás;2 – Possua, no máximo, dois pontos de destino em cada função.
Com isso, você pode se divertir a vontade!É isso!
P.s.: Como somos politicamente incorretos, não poderíamos deixar de falar do COMEFROM, que é basicamente o oposto do GOTO!O COMEFROM surgiu como uma piada de Assembly:
http://c2.com/cgi/wiki?ComeFrom
Não possui nenhuma utilidade a não ser bagunçar seu código, mas se você quiser se exibir para os outros, aqui vai um port do COMEFROM para C:

#define _(A) goto A;
#define COME_FROM(A) A:
int main(){&nbsp;&nbsp;&nbsp; int x = 0;&nbsp;&nbsp;&nbsp; int y = 0;
&nbsp;&nbsp;&nbsp; COME_FROM( fim_loop );
&nbsp;&nbsp;&nbsp; ++x;&nbsp;&nbsp;&nbsp; ++y;
&nbsp;&nbsp;&nbsp; _( fim_loop )
&nbsp;&nbsp;&nbsp; return 0;}
Boa sorte! :)