Pregunta

goto es casi universalmente desanimado.Es uso de esta instrucción siempre vale la pena?

¿Fue útil?

Solución

Esto se ha discutido varias veces en Stack Overflow y Chris Gillum resumió los posibles usos de goto:

Salir limpiamente de una función

A menudo en una función, puede asignar recursos y necesitar salir en múltiples lugares. Los programadores pueden simplificar su código colocando el código de limpieza de recursos al final de la función Todos los "puntos de salida" de la función obtendrían la etiqueta de limpieza. De esta manera, no tiene que escribir código de limpieza en cada "punto de salida" de la función.

Salir de bucles anidados

Si estás en un bucle anidado y necesitas salir de todos bucles, un GoTo puede hacer tanto más limpio y simple que las declaraciones de descanso y las verificaciones de IF.

Mejoras de rendimiento de bajo nivel

Esto solo es válido en código de perfricia, pero las declaraciones de GOTO se ejecutan muy rápidamente y pueden darle un impulso al moverse a través de una función. Sin embargo, esta es una espada de doble filo, porque un compilador generalmente no puede optimizar el código que contiene GOTOS.

Argumentaría, como muchos otros argumentarían, que en todos estos casos, el uso de goto se usa como un medio para salir de una esquina en la que se codifica, y generalmente es un síntoma de código que podría refactorizarse.

Otros consejos

Las construcciones de flujo de control de nivel superior tienden a corresponder a conceptos en el dominio del problema. Un if/else es una decisión basada en alguna condición. Un bucle dice que realice alguna acción repetidamente. Incluso una declaración de descanso dice que "estábamos haciendo esto repetidamente, pero ahora tenemos que parar".

Una declaración GOTO, por otro lado, tiende a corresponder a un concepto en el programa de ejecución, no en el dominio del problema. Dice continuar la ejecución en un punto especificado en el programa. Alguien que lea el código tiene que inferir Lo que eso significa con respecto al dominio del problema.

Por supuesto, todas las construcciones de nivel superior se pueden definir en términos de gotos y ramas condicionales simples. Eso no significa que simplemente sean disfrazados. Piense en ellos como restringido Gotos, y son las restricciones las que las hacen útiles. Se implementa una declaración de descanso como un salto al final del circuito de adjunto, pero se considera mejor que funciona en el bucle en su conjunto.

Todo lo demás es igual, código cuya estructura refleja la del dominio del problema tiende a ser más fácil de leer y mantener.

No hay casos en los que se requiere una declaración de GOTO (hay Teorema a ese sentido), pero hay casos en los que puede ser la solución menos mala. Esos casos varían de un lenguaje a otro, dependiendo de qué construcciones de nivel superior admite el lenguaje.

En C, por ejemplo, creo que hay tres escenarios básicos en los que un GoTo es apropiado.

  1. Romper con un bucle anidado. Esto sería innecesario si el lenguaje tuviera una declaración de descanso etiquetada.
  2. Saliendo de un tramo de código (típicamente un cuerpo de funciones) en caso de un error u otro evento inesperado. Esto sería innecesario si el lenguaje tuviera excepciones.
  3. Implementación de una máquina de estado finito explícita. En este caso (y, creo, solo en este caso) un GoTo corresponde directamente a un concepto en el dominio del problema, pasando de un estado a un otro estado específico, donde el estado actual está representado por el cual el bloque de código se está ejecutando actualmente actualmente .

Por otro lado, una máquina de estado finito explícita también se puede implementar con una instrucción Switch dentro de un bucle. Esto tiene la ventaja de que cada estado comienza en el mismo lugar en el código, que puede ser útil para la depuración, por ejemplo.

El uso principal de un GoTo en un lenguaje razonablemente moderno (uno que admite si/else y bucles) es simular una construcción de flujo de control que falta en el idioma.

Seguramente depende del lenguaje de programación. La razón principal goto ha sido controvertido se debe a sus efectos nocivos que surgen cuando el compilador le permite usarlo demasiado liberalmente. Pueden surgir problemas, por ejemplo, si le permite usar goto De tal manera que ahora puede acceder a una variable no inicializada, o peor, para saltar a otro método y meterse con la pila de llamadas. Debería ser responsabilidad del compilador no permitir el flujo de control sin sentido.

Java ha intentado "resolver" este problema al no permitir goto enteramente. Sin embargo, Java te permite usar return dentro de una finally bloquear y, por lo tanto, hacer que una excepción se trague inadvertidamente. El mismo problema sigue ahí: el compilador no está haciendo su trabajo. Eliminación goto del lenguaje no lo ha arreglado.

Cía#, goto es tan seguro como break, continue, try/catch/finally y return. No le permite usar variables no inicializadas, no le permite saltar de un bloque finalmente, etc. El compilador se quejará. Esto es porque resuelve el real Problema, que es como dije que el flujo de control sin sentido. goto No cancele mágicamente el análisis de asignación definitiva y otras verificaciones de compiladores razonables.

Sí. Cuando tus bucles están anidados varios niveles de profundidad, goto es el solamente forma de romper elegantemente un bucle interno. La otra opción es establecer una bandera y salir de cada bucle si ese indicador satisface una condición. Esto es realmente feo y bastante propenso a errores. En estos casos, goto es simplemente mejor.

Por supuesto, Java está etiquetado break La declaración hace lo mismo, pero sin permitirle saltar a un punto arbitrario en el código, que resuelve el problema perfectamente sin permitir las cosas que hacen goto demonio.

La mayoría de los desánimo viene de una especie de "religión" que ha sido creado aroud Dios Djikstra que era convincente en la década de los '60 sobre es indiscriminado de alimentación a:

  • saltar a cualquier lugar en cualquier bloque de código
    • la función no se ejecuta desde el principio
    • los bucles no se ejecuta desde el principio
    • salteado de inicialización de la variable
  • salto de distancia de cualquier bloque de código sin ningún tipo de limpieza.

Esto no tiene nada más que hacer con el goto declaración de las lenguas modernas, cuya existencia es meramente debido a apoyar la creación de estructuras de código que no sea el idioma que se proveen.

En particular, el primer punto principal de arriba es más permitida y la segunda es limpiado (si goto a partir de un bloque de la pila es unwinded correctamente y todo correcto destructores llamado)

Usted puede referir a esta respuesta para tener una idea de cómo, incluso el código no usar goto puede ser ilegible.El problema no es ir a sí mismo, pero el mal uso de la misma.

Puedo escribir un programa entero sin usar if, sólo for.Por supuesto, no va a ser bien legibles, una mirada torpe y complicado innecesariamente.

Pero el problema no es for.Es a mí.

Cosas como break, continue, throw, bool needed=true; while(needed) {...}, etc.se observa más de la mascarada goto para escapar lejos de las cimitarras de los Djikstrarian zelotes, que -50 años después de la invención de los modernos idiomas - todavía quiere a sus prisioneros.Se olvidaron de lo que Djikstra estaba hablando, sólo recuerdo el título de su nota (GOTO considera peligroso, y ni siquiera era su onw título:fue cambiado por el editor), de la culpa y bash bash y la culpa de cada reconstruir el hecho de tener esas 4 letras colocadas en secuencia.

Es 2011:es hora de entender que goto se ha de señalar que lidiar con la GOTO declaración de Djikstra era convincente acerca de.

El extraño geto aquí o allá, siempre que sea local para una función, rara vez perjudica significativamente la legibilidad. A menudo lo beneficia llamando la atención sobre el hecho de que hay algo inusual en este código que requiere el uso de una estructura de control algo poco común.

Si los gotos (locales) están dañando significativamente la legibilidad, entonces generalmente es una señal de que la función que contiene el GoTo se ha vuelto demasiado compleja.

El último GoTo que puse en un código C fue construir un par de bucles entrelazados. No se ajusta a la definición normal de uso "aceptable", pero la función terminó significativamente más pequeña y clara como resultado. Para evitar el GoTo habría requerido una violación particularmente desordenada de seco.

Creo que todo este problema ha sido un caso de ladrar el árbol equivocado.

GOTO como tal no me parece problemático, sino que a menudo es un síntoma de un pecado real: el código de espagueti.

Si el GoTo causa un importante cruce de líneas de control de flujo, entonces es malo, período. Si no cruza las líneas de control de flujo, es inofensivo. En la zona gris en el medio tenemos cosas como rescates de bucle, todavía hay algunos idiomas que no han agregado construcciones que cubren todos los casos de gris legítimo.

El único caso que me encontré realmente usándolo en muchos años es el caso del bucle donde el punto de decisión está en el medio del bucle. Te queda con código duplicado, una bandera o un GoTo. Encuentro la solución GOTO lo mejor de los tres. No hay un cruce de líneas de control de flujo aquí, es inofensivo.

Sí, el GoTo se puede usar para beneficiar la experiencia del desarrollador:http://adamjonrichardson.com/2012/02/06/long-live-the-goto-statement/

Sin embargo, al igual que con cualquier herramienta poderosa (punteros, herencia múltiple, etc.), uno debe ser disciplinado al usarla. El ejemplo proporcionado en el enlace utiliza PHP, que restringe el uso de la construcción GOTO a la misma función/método y deshabilita la capacidad de saltar a un nuevo bloque de control (por ejemplo, la declaración de bucle, el interruptor, etc.)

Depende del idioma. Todavía se usa ampliamente en la programación de Cobol, por ejemplo. También he trabajado en un dispositivo Barionet 50, cuyo lenguaje de programación de firmware es un dialecto básico temprano que, por supuesto, requiere que use GOTO.

Yo diría que no. Si encuentra la necesidad de usar GOTO, apuesto a que existe la necesidad de rediseñar el código.

goto puede ser útil cuando se portan código de ensamblador heredado a C. En primera instancia, una conversión de instrucción por instrucción a C, usando goto como reemplazo del ensamblador branch Instrucción, puede habilitar una portada muy rápida.

Yo diría que no. Siempre deben ser reemplazados por una herramienta más específica del problema que GOTO se está utilizando para resolver (a menos que no esté disponible en su idioma). Por ejemplo, las declaraciones y las excepciones de ruptura resuelven a problemas previamente resueltos de escape y manejo de errores de bucle.

Licenciado bajo: CC-BY-SA con atribución
scroll top