VGrabko
@VGrabko
Golang, Php, Js

Почему goto зло?

Я читал кучу книг и везде сказано что GOTO это филиал ада на земле. Но я вот понять не могу почему его так ругают? (камни не кидайте! Я его не юзаю)

Почему вместо рекурсии не заюзать goto?
Ну очень понятный код выходит:
func () string {
small:
	id := generateString(32)
	if unique(id) {
		goto small
	}
	return id
}
  • Вопрос задан
  • 3522 просмотра
Решения вопроса 7
maaGames
@maaGames
Погроммирую программы
Потому что не зло, просто "красивая" легенда.
Ответ написан
Комментировать
@dmitryKovalskiy
программист средней руки
Код то может и понятный, но тупой. Id должен быть сгенерирован уникальным, а не проверятся потом уникальный получился или нет(или что он вообще делает). Тот же код без goto
do
{
id = GenerateString(32)
}while(unique(id))


Порядок выполнения кода должен быть понятен. Бросание хода выполнения по меткам понимания не добавляет.
Вот вам пример из C#
try{
a=3;
return a;
}
catch{
a=0;
return a;
}
finaly
{
a=5;
}

И вот эта конструкция вполне допустима, но многие молодые программисты споткнутся и не ответят что вернет функция. Причина? неявный goto. Вы привели в пример код с 1 переходом. А если таких переходов 5-10 и они не последовательны. Т.е. один внутри другого, третий сбоку. Любую задачу, которая решается использованием goto можно реализовать циклами, суперпозицией и другими более простыми инструкциями. Вопрос - зачем использовать goto? Приведите пример, в котором код на goto выглядит проще и очевиднее чем циклы и прочее - используйте goto. В других случаях применение goto не оправдан и кроме недоумения, при анализе кода, не вызывает ничего.
Ответ написан
index0h
@index0h
PHP, Golang. https://github.com/index0h
Потому, что сложно читать и дебажить так как ваш код выполняется в хрен знает какой последовательности. Ваш метод на 6 строк, как пример - так себе. Если метод на 300-400, и этих goto штук 15? Не запуская код с таймером, выпишите на бумажку что будет выведено на экран в таком примере (там всего 50 строк).
Код с goto пишется один раз, а дальше выбрасывается.

З.Ы. Конкретно ваш пример стоит делать в цикле и рекурсия вам тут тоже не нужна.

func () (id string) {
	for id = generateString(32); unique(id); id = generateString(32) {
	}

	return id
}
Ответ написан
0xcffaedfe
@0xcffaedfe
Developer & Reverser
goto не зло, просто им нужно уметь пользоваться, anyway компиль все равно вставит jmp если нужно. Да и вообще компиляторы нынче шибко умные.
Оригинал вида:
#include <iostream>
void dd();

int main(int argc, const char * argv[]) {
    
s:
    if(rand() % 100 == 99){
        goto e;
    }
    goto s;
e:
    return 0;
}


Кошерно превращает в обычный цикл:
int _main(int arg0, int arg1) {
    do {
            rax = rand();
            temp_3 = rax % 0x64;
            if (temp_3 == 0x63) {
                break;
            }
    } while (true);
    return 0x0;
}


ну и на асме.

_main:
                    push       rbp
                    mov        rbp, rsp
                    sub        rsp, 0x10
                    mov        dword [ss:rbp+var_4], 0x0
                    mov        dword [ss:rbp+var_8], edi
                    mov        qword [ss:rbp+var_10], rsi
_100000f66:       call       imp___stubs__rand
                    mov        ecx, 0x64
                    cdq        
                    idiv       ecx
                    cmp        edx, 0x63
                    jne        _100000f81
                    jmp        _100000f86
_100000f81:       jmp        _100000f66
_100000f86:       xor        eax, eax
                    add        rsp, 0x10
                    pop        rbp
                    ret
Ответ написан
@iv_k
goto - тяжелое наследие ассемблерщиков, переходящих на си.
можно обойтись и без него.
хотя.. гляньте ядро линукс, там goto полно.
например вот так
foo()
{
   if(..)
   {
        goto err;
   }
   if (...)
   {
      goto err;
   }
    on_success();
    return ok;
err:
    on_error();
    return error;
}


вот тут достаточно просто для понимания
Ответ написан
Комментировать
@evgeniy_lm
Goto тупо меняет направление выполнения программы, причем метка перехода может быть где угодно и проследить логику очень трудно. В то время как существует масса операторов (циклы, условия, ветвления) логика работы которых доступна пониманию.
Ответ написан
Комментировать
@milast
все пишут, что GOTO зло, но не всегда и не везде.
Самое удачное его применение может быть для выхода из цикла.

var a uint8
var key uint8 = 7

for  {
        switch a {
        case key-1:
                fmt.Println("left")
        case key:
                goto exit
        }

        a++
}
exit:
fmt.Println("End")
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы