goto
é quase universalmente desencorajado. Vale a pena usar essa declaração?
goto
programming-practices
Casebash
fonte
fonte
goto
é o que a CPU faz, em última análise, mas não funciona bem com o que os humanos precisam compreender e abstrair porque não há marca no alvo. Compare com IntercalCOMEFROM
.goto
é claro que não é necessário. É apenas a maneira mais racional de implementá-las nas linguagens imperativas, já que é a coisa mais próxima da própria semântica da transição de estado. E seu destino pode estar bem longe da fonte, não prejudicará a legibilidade. Meu exemplo favorito desse código é a implementação de DE Knuth do jogo Adventure.Respostas:
Isso foi discutido várias vezes no Stack Overflow, e Chris Gillum resumiu os possíveis usos de
goto
:Eu argumentaria, como muitos outros argumentariam, que em todos esses casos, o uso de
goto
é usado como um meio de sair de um canto em que um codificado foi inserido e geralmente é um sintoma de código que pode ser refatorado.fonte
finally
blocos nas línguas modernas, e o segundo é resolvido porbreak
s. No entanto,goto
se você está preso ao C, é praticamente a única maneira de resolver esses problemas com elegância.finally
é válido apenas nessas condições. Existem situações muito raras, mas válidas, em que um goto é o caminho a percorrer.break 3
oubreak myLabel
egoto myLabel
? Ah, isso mesmo, apenas a palavra-chave. Se você estiver usandobreak
,continue
ou alguma palavra-chave semelhante você está infact usando umgoto
(se você estiver usandofor, while, foreach, do/loop
você estiver usando um goto condicional.)As construções de fluxo de controle de nível superior tendem a corresponder aos conceitos no domínio do problema. Um if / else é uma decisão baseada em alguma condição. Um loop diz para executar alguma ação repetidamente. Até uma declaração de pausa diz "estávamos fazendo isso repetidamente, mas agora precisamos parar".
Uma declaração goto, por outro lado, tende a corresponder a um conceito no programa em execução, não no domínio do problema. Ele diz para continuar a execução em um ponto especificado no programa . Alguém que lê o código precisa inferir o que isso significa em relação ao domínio do problema.
É claro que todas as construções de nível superior podem ser definidas em termos de gotos e ramificações condicionais simples. Isso não significa que eles são apenas gotos disfarçados. Pense neles como gotos restritos - e são as restrições que os tornam úteis. Uma declaração de interrupção é implementada como um salto para o final do loop fechado, mas é melhor pensar em operar no loop como um todo.
Sendo tudo igual, o código cuja estrutura reflete a do domínio do problema tende a ser mais fácil de ler e manter.
Não há casos em que uma declaração goto seja absolutamente necessária (há um teorema nesse sentido), mas há casos em que pode ser a solução menos ruim. Esses casos variam de idioma para idioma, dependendo das construções de nível superior que o idioma suporta.
Em C, por exemplo, acredito que há três cenários básicos em que um goto é apropriado.
Por outro lado, uma máquina explícita de estados finitos também pode ser implementada com uma instrução switch dentro de um loop. Isso tem a vantagem de que todo estado inicia no mesmo local no código, o que pode ser útil para depuração, por exemplo.
O principal uso de um goto em uma linguagem razoavelmente moderna (que suporta if / else e loops) é simular uma construção de fluxo de controle que está faltando na linguagem.
fonte
goto
. Os SSSM geralmente são boas estruturas para usar, pois separam o estado SM da construção de execução, mas na verdade não eliminam "gotos".Certamente depende da linguagem de programação. A principal razão da
goto
controvérsia é por causa dos efeitos nocivos que surgem quando o compilador permite que você o use com muita liberalidade. Podem surgir problemas, por exemplo, se ele permite que você use degoto
maneira que agora você possa acessar uma variável não inicializada, ou pior, para pular para outro método e mexer na pilha de chamadas. Deve ser responsabilidade do compilador proibir o fluxo de controle sem sentido.Java tentou "resolver" esse problema, impedindo
goto
completamente. No entanto, o Java permite que você usereturn
dentro de umfinally
bloco e, portanto, faz com que uma exceção seja engolida inadvertidamente. O mesmo problema ainda está lá: o compilador não está fazendo seu trabalho. A remoçãogoto
do idioma não foi corrigida.Em C #,
goto
é tão segura comobreak
,continue
,try/catch/finally
ereturn
. Ele não permite que você use variáveis não inicializadas, não deixa você pular de um bloco finalmente etc. O compilador irá reclamar. Isso ocorre porque resolve o problema real , como eu disse no fluxo de controle sem sentido.goto
não cancela magicamente a análise de atribuição definida e outras verificações razoáveis do compilador.fonte
goto
não é mau? Se assim for, que é o caso para cada linguagem moderna rotineiramente usado com umagoto
construção, não só C # ...Sim. Quando seus loops estão aninhados em vários níveis de profundidade,
goto
é a única maneira de sair elegantemente de um loop interno. A outra opção é definir um sinalizador e interromper cada loop se esse sinalizador satisfizer uma condição. Isso é realmente feio e propenso a erros. Nestes casos,goto
é simplesmente melhor.Obviamente, a
break
declaração rotulada de Java faz a mesma coisa, mas sem permitir que você pule para um ponto arbitrário no código, que resolve o problema perfeitamente, sem permitir as coisas que fazemgoto
mal.fonte
Do
loop. Por quê? Porque eu posso mudar o loop que precisa de uma quebra profunda em umDo
loop e digitarExit Do
e não háGoTo
. Loops aninhados acontecem o tempo todo. Quebrar as pilhas acontece algumas vezes.A maior parte do desânimo vem de uma espécie de "religião" criada em meio a Deus Djikstra, que foi convincente no início dos anos 60 sobre seu poder indiscriminado de:
Isso não tem mais nada a ver com a
goto
declaração das linguagens modernas, cuja existência se deve apenas ao suporte à criação de estruturas de código diferentes das fornecidas pela linguagem.Em particular, o primeiro ponto principal acima é mais permitido e o segundo é limpo (se você
goto
sair de um bloco, a pilha será desenrolada adequadamente e todos os destruidores adequados serão chamados)Você pode consultar esta resposta para ter uma idéia de como mesmo o código que não usa goto pode ser ilegível. O problema não é ir sozinho, mas o mau uso dele.
Eu posso escrever um programa inteiro sem usar
if
, apenasfor
. Obviamente, não será bem legível, uma aparência desajeitada e desnecessariamente complicada.Mas o problema não é
for
. Sou eu.Coisas como
break
,continue
,throw
,bool needed=true; while(needed) {...}
, etc. estão observando mais de máscarasgoto
para escapar longe das cimitarras dos fanáticos Djikstrarian, que -50 anos depois da invenção da laguages- moderna ainda querem que seus prisioneiros. Eles esqueceram o que Djikstra estava falando, lembram-se apenas do título de sua nota (GOTO considerado prejudicial, e nem era o título dele: foi alterado pelo editor) e culpar e bash, bash e culpar todos os contrutos que possuem aqueles 4 carta colocada em sequência.Chegou o ano de 2011: é hora de entender que é
goto
preciso notar aGOTO
afirmação de que Djikstra era convincente.fonte
break n
não está disponível em C ++, portantogoto escape
, mesmo queescape
não seja necessário sair do loop n-ple.O goto estranho aqui ou ali, desde que seja local para uma função, raramente prejudica significativamente a legibilidade. Muitas vezes, é benéfico chamando a atenção para o fato de que há algo incomum nesse código que requer o uso de uma estrutura de controle um tanto incomum.
Se os gotos (locais) estão prejudicando significativamente a legibilidade, geralmente é um sinal de que a função que contém o goto se tornou muito complexa.
O último passo que eu coloquei em um pedaço de código C foi construir um par de loops interligados. Não se encaixa na definição normal de uso "aceitável" do goto, mas a função acabou sendo significativamente menor e mais clara como resultado. Para evitar o goto, seria necessária uma violação particularmente desordenada do DRY.
fonte
Eu acho que toda essa questão foi um caso de latir na árvore errada.
GOTO, como tal, não me parece problemático, mas muitas vezes é um sintoma de um pecado real: código de espaguete.
Se o GOTO causar uma grande travessia das linhas de controle de fluxo, está ruim, ponto final. Se não cruzar nenhuma linha de controle de fluxo, é inofensivo. Na zona cinza entre nós temos coisas como salvamentos em loop, ainda existem alguns idiomas que não adicionaram construções que cobrem todos os casos cinza legítimos.
O único caso em que eu realmente o uso em muitos anos é o caso do loop em que o ponto de decisão está no meio do loop. Você fica com código duplicado, uma bandeira ou um GOTO. Acho a solução GOTO a melhor das três. Não há cruzamento de linhas de controle de fluxo aqui, é inofensivo.
fonte
goto
s que pulam em um loop (se o idioma permitir; se o idioma permitir; já no outro caso, pular fora do circuito no meio, geralmente é trivial semgoto
).goto
em gritar: O FLUXO DE CONTROLE AQUI NÃO SE ENCONTRA PADRÕES NORMAIS DE PROGRAMAÇÃO ESTRUTURADA . Como os fluxos de controle que se ajustam aos padrões de programação estruturados são mais fáceis de raciocinar do que aqueles que não o fazem, deve-se tentar usar esses padrões sempre que possível; se o código se encaixa nesses padrões, não se deve gritar que não. Por outro lado, nos casos em que o código realmente não se encaixa nesses padrões, gritar sobre isso pode ser melhor do que fingir que o código se encaixa quando realmente não se encaixa.Sim, o goto pode ser usado para beneficiar a experiência do desenvolvedor: http://adamjonrichardson.com/2012/02/06/long-live-the-goto-statement/
No entanto, assim como com qualquer ferramenta poderosa (ponteiros, herança múltipla etc.), é preciso ser disciplinado usando-a. O exemplo fornecido no link usa PHP, que restringe o uso da construção goto para a mesma função / método e desativa a capacidade de saltar para um novo bloco de controle (por exemplo, loop, instrução switch, etc.)
fonte
Depende do idioma. Ainda é amplamente utilizado na programação Cobol, por exemplo. Também trabalhei em um dispositivo Barionet 50, cuja linguagem de programação de firmware é um dialeto BASIC antigo que, naturalmente, exige que você use Goto.
fonte
Eu diria que não. Se você achar necessário usar o GOTO, aposto que é necessário redesenhar o código.
fonte
goto
pode ser útil ao portar o código do assembler legado para C. Na primeira instância, uma conversão de instrução por instrução para C, usandogoto
como um substituto para abranch
instrução do assembler , pode permitir a portabilidade muito rápida.fonte
Eu diria que não. Eles sempre devem ser substituídos por uma ferramenta mais específica para o problema que o goto está sendo usado para resolver (a menos que não esteja disponível no seu idioma). Por exemplo, instruções e exceções de quebra resolvem problemas anteriormente resolvidos para goto de escape de loop e manipulação de erros.
fonte
goto
normalmente eles estão ausentes.goto
a coisa mais próxima da semântica do domínio do problema é que qualquer outra coisa seria um hack sujo.