goto
почти повсеместно обескуражен. Стоит ли когда-либо использовать это утверждение?
goto
programming-practices
Casebash
источник
источник
goto
это то, что в конечном итоге делает процессор, но он плохо работает с тем, что людям нужно понимать и абстрагировать из-за отсутствия отметки на целевом конце. Сравните с IntercalCOMEFROM
.goto
, не требуется. Это просто наиболее рациональный способ их реализации на императивных языках, поскольку он наиболее близок к самой семантике перехода между состояниями. И его назначение может быть довольно далеко от источника, это не будет мешать удобочитаемости. Мой любимый пример такого кода - реализация приключенческой игры DE Knuth.Ответы:
Это несколько раз обсуждалось на переполнении стека, и Крис Гиллум суммировал возможные варианты использования
goto
:Я бы поспорил, как утверждают многие другие, что во всех этих случаях использование
goto
используется как средство выхода из угла, в который вы себя закодировали, и, как правило, является признаком кода, который можно реорганизовать.источник
finally
блоков в современных языках, а вторая решается с помощьюbreak
s. Однако, если вы застряли на C,goto
это практически единственный способ элегантного решения этих проблем.finally
допустимо только в этих условиях. Есть очень редкие, но допустимые ситуации, когда goto - это путь.break 3
илиbreak myLabel
иgoto myLabel
. О, это верно только ключевое слово. Если вы используетеbreak
,continue
или какое-то похожее ключевое слово, вы на самом деле используетеgoto
(Если вы используете,for, while, foreach, do/loop
вы используете условный переход.)Конструкции потока управления более высокого уровня, как правило, соответствуют понятиям в проблемной области. If / else - это решение, основанное на некотором условии. Цикл говорит, что нужно выполнить какое-то действие повторно. Даже в заявлении о перерыве говорится, что «мы делали это неоднократно, но теперь нам нужно остановиться».
Оператор goto, с другой стороны, имеет тенденцию соответствовать концепции в запущенной программе, а не в проблемной области. Он говорит, чтобы продолжить выполнение в указанной точке программы . Кто-то, читающий код, должен сделать вывод, что это означает в отношении проблемной области.
Конечно, все конструкции более высокого уровня могут быть определены в терминах gotos и простых условных ветвей. Это не значит, что они просто замаскированы. Думайте о них как об ограниченных действиях - и именно ограничения делают их полезными. Оператор break реализован как переход к концу окружающего цикла, но его лучше рассматривать как работу с циклом в целом.
При прочих равных условиях код, структура которого отражает структуру проблемной области, легче читать и поддерживать.
Не существует случаев, когда оператор goto абсолютно необходим ( на этот счет есть теорема ), но есть случаи, когда это может быть наименее плохим решением. Эти случаи варьируются от языка к языку, в зависимости от того, какие конструкции более высокого уровня поддерживает язык.
Например, в Си я считаю, что есть три основных сценария, в которых уместно использовать goto.
С другой стороны, явный конечный автомат также может быть реализован с помощью оператора switch внутри цикла. Это имеет то преимущество, что каждое состояние начинается в одном и том же месте в коде, что может быть полезно, например, для отладки.
Основное использование goto на достаточно современном языке (который поддерживает if / else и циклы) - это имитация конструкции потока управления, которая отсутствует в языке.
источник
goto
. SSSM часто являются хорошими структурами для использования, поскольку они отделяют состояние SM от конструкции исполнения, но на самом деле они не устраняют "gotos".Конечно, это зависит от языка программирования. Основная причина
goto
является спорным из - за его негативные последствия , которые возникают , когда компилятор позволяет использовать его слишком обильно. Проблемы могут возникнуть, например, если он позволяет вам использоватьgoto
таким образом, что вы теперь можете получить доступ к неинициализированной переменной или, что еще хуже, перейти к другому методу и связываться со стеком вызовов. Это должно быть обязанностью компилятора запретить бессмысленный поток управления.Java попыталась «решить» эту проблему,
goto
полностью запретив . Однако Java позволяет вам использоватьreturn
внутриfinally
блока и, таким образом, непреднамеренно проглатывать исключение. Та же проблема все еще существует: компилятор не выполняет свою работу. Удалениеgoto
из языка не исправило это.В C #,
goto
является таким же безопасным , какbreak
,continue
,try/catch/finally
иreturn
. Он не позволяет использовать неинициализированные переменные, не позволяет выпрыгнуть из блока finally и т. Д. Компилятор будет жаловаться. Это потому, что это решает реальную проблему, которая, как я сказал, бессмысленный поток управления.goto
магически не отменяет анализ с определенным назначением и другие разумные проверки компилятором.источник
goto
не является злом? Если это так, то так обстоит дело с каждым обычно используемым современным языком сgoto
конструкцией, а не только с C # ...Да. Когда ваши петли вложены в несколько уровней глубиной,
goto
это единственный способ элегантно вырваться из внутренней петли. Другой вариант - установить флаг и выйти из каждого цикла, если этот флаг удовлетворяет условию. Это действительно некрасиво и довольно подвержено ошибкам. В этих случаяхgoto
просто лучше.Конечно, помеченный
break
оператор Java делает то же самое, но не позволяет вам перейти к произвольной точке в коде, что решает проблему аккуратно, не допуская того, что создаетgoto
зло.источник
Do
цикл. Зачем? Потому что я могу изменить один цикл, который нуждается в глубоком разрыве вDo
цикл и набирать текст,Exit Do
а там нетGoTo
. Вложенные циклы случаются все время. Разбиение стеков происходит в некоторых случаях.Большая часть разочарования происходит от своего рода «религии», которая была создана с гордостью Бога Джикстра, который убедил в начале 60-х о своей неизбирательной силе:
Это не имеет ничего общего с
goto
утверждением современных языков, существование которых обусловлено исключительно поддержкой создания структур кода, отличных от предоставляемых языком.В частности, первый основной пункт, приведенный выше, больше разрешен, а второй очищен (если вы
goto
вышли из блока, стек распаковывается правильно и вызываются все нужные деструкторы)Вы можете сослаться на этот ответ, чтобы иметь представление о том, как даже код, не использующий goto, может быть нечитаемым. Проблема не в самом Гото, а в плохом его использовании.
Я могу написать всю программу без использования
if
, простоfor
. Конечно, он не будет хорошо читаемым, выглядит неуклюжим и излишне сложным.Но проблема не в этом
for
. Это я.Такие вещи , как
break
,continue
,throw
,bool needed=true; while(needed) {...}
и т.д., отмечая более маскарадаgoto
, чтобы уйти подальше от скимитаров этих Djikstrarian фанатиков, что -50 лет после изобретения современного laguages- все еще хотят , чтобы их заключенный. Они забыли, о чем говорил Джикстра, они помнят только название его заметки (GOTO считал вредным, и это даже не было его новым заголовком: оно было изменено редактором), а также обвиняют и ругают, ругают и обвиняют каждый конструкт, имеющий эти 4 письмо в последовательности.Наступил 2011 год: пришло время понять, что не
goto
стоит разбираться сGOTO
заявлением, о котором Джикстра был убедителен.источник
break n
недоступна в C ++, следовательноgoto escape
, даже еслиescape
не требуется просто выходить из цикла n-ple.Странный переход здесь или там, если он локальный для функции, редко значительно ухудшает читабельность. Это часто приносит пользу, привлекая внимание к тому факту, что в этом коде происходит что-то необычное, что требует использования несколько необычной структуры управления.
Если (локальные) goto значительно ухудшают читабельность, то обычно это признак того, что функция, содержащая goto, стала слишком сложной.
Последнее, что я вставил в фрагмент кода C, - это построение пары взаимосвязанных циклов. Он не вписывается в обычное определение «приемлемого» использования, но в результате функция стала значительно меньше и понятнее. Чтобы избежать goto, потребовалось бы особенно грязное нарушение DRY.
источник
Я думаю, что весь этот вопрос был случай лая неправильное дерево.
GOTO как таковое не кажется мне проблематичным, скорее, это очень часто признак настоящего греха: спагетти-код.
Если GOTO вызывает значительное пересечение линий контроля потока, то это плохо, точка. Если он не пересекает линии контроля потока, он безвреден. В серой зоне между нами есть такие вещи, как спасение цикла, все еще есть некоторые языки, в которых не добавлены конструкции, охватывающие все допустимые случаи серого.
Единственный случай, когда я на самом деле использовал его в течение многих лет, - это случай цикла, когда точка принятия решения находится в середине цикла. У вас остается либо дублированный код, флаг или GOTO. Я нахожу решение GOTO лучшим из трех. Здесь нет пересечения линий контроля потока, это безвредно.
источник
goto
s, которые переходят в цикл (если язык позволяет это; так как в другом случае, прыжок вне цикла в середине, обычно тривиально безgoto
).goto
как выкрикивая КОНТРОЛЬ РАСХОД ЗДЕСЬ НЕ FIT НОРМАЛЬНЫХ СТРУКТУРИРОВАННОГО-ПРОГРАММИРУЮЩИЕ РИСУНКИ . Поскольку потоки управления, которые соответствуют шаблонам структурированного программирования, легче рассуждать, чем те, которые этого не делают, следует по возможности использовать такие шаблоны; если код соответствует таким шаблонам, не следует кричать, что это не так. С другой стороны, в случаях, когда код действительно не соответствует таким шаблонам, кричать об этом может быть лучше, чем притворяться, что код подходит, когда это действительно не подходит.Да, goto можно использовать для получения опыта разработчика: http://adamjonrichardson.com/2012/02/06/long-live-the-goto-statement/
Однако, как и в случае с любым мощным инструментом (указатели, множественное наследование и т. Д.), Его нужно дисциплинировать, используя его. В приведенном в ссылке примере используется PHP, который ограничивает использование конструкции goto той же функцией / методом и отключает возможность перехода в новый блок управления (например, цикл, оператор switch и т. Д.).
источник
Зависит от языка. Например, он до сих пор широко используется в программировании на Cobol. Я также работал над устройством Barionet 50, язык программирования микропрограмм которого является ранним бейсиковым диалектом, который, конечно, требует от вас использования Goto.
источник
Я бы сказал нет. Если вы обнаружите необходимость использования GOTO, держу пари, что есть необходимость переделать код.
источник
goto
может быть полезно при переносе старого кода ассемблера на C. В первом случае преобразование инструкции за инструкцией в C, использующееgoto
в качестве заменыbranch
инструкцию на ассемблере , может позволить очень быстрое перенос.источник
Я бы сказал, что нет. Их всегда следует заменять инструментом, более специфичным для проблемы, для решения которой используется goto (если она недоступна на вашем языке). Например, операторы break и исключения решают ранее решенные проблемы выхода из цикла и обработки ошибок.
источник
goto
обычно отсутствуют в этих языках.goto
наиболее близкая вещь к семантике предметной области очень проблемна, и все остальное было бы грязным хаком.