Код Go не компилируется без недостижимого оператора return - программирование
Подтвердить что ты не робот

Код Go не компилируется без недостижимого оператора return

Вот программа для поиска факториала числа в Go:

func factorial(x uint) uint {
    if x == 0 {
        return 1
    }

    return x * (factorial(x - 1))
}

Выход для этой функции при вызове на входе 5 равен 120. Однако, если я добавляю оператор else, я получаю сообщение об ошибке.

func factorial(x uint) uint {
    if x == 0 {
        return 1
    } else {
        return x * (factorial(x - 1))
    }
}

Ошибка: function ends without a return statement

Я добавил в конце return:

func factorial(x uint) uint {
    if x == 0 {
        return 1
    } else {
        return x * (factorial(x - 1))
    }
    fmt.Println("this never executes")
    return 1
}

и я возвращаю ожидаемый результат 120.

Почему второй случай вызвал ошибку? Почему в третьем случае, даже если функция никогда не достигает последнего return 1, он вычисляет правильный вывод?

4b9b3361

Ответ 1

Это хорошо известная проблема компилятора.

Существует даже проблема: http://code.google.com/p/go/issues/detail?id=65

По словам одного из авторов языка Go:

Для компиляторов требуется либо возврат, либо паника, чтобы лексически последний в функции с результатом. Это правило проще, чем полное анализ управления потоком, чтобы определить, заканчивается ли функция без возврата (что очень сложно вообще) и проще, чем правила перечисления таких простых случаев, как этот. Кроме того, будучи чисто лексический, ошибка не может возникнуть спонтанно из-за изменений в значениях такие как константы, используемые в управляющих структурах внутри функции.

Роб

Из другого комментария в golang-nuts, мы можем предположить, что он скоро не будет исправлен:

Это не ошибка, это продуманное дизайнерское решение.

Роб

Обратите внимание, что другие языки, такие как Java, имеют правила, разрешающие это else.


Март 2013 EDIT - Просто изменился в Go1.1:

Перед тем, как Go 1.1, функция, которая вернула значение, потребовала явного "вернуться" или вызвать панику в конце функции; это было простой способ заставить программиста быть явным о значении функция. Но есть много случаев, когда окончательное "возвращение" очевидно ненужной, такой как функция с только бесконечным циклом "для".

В Go 1.1 правило о заключительных операциях "return" больше разрешающий. В нем представлена ​​концепция терминального утверждения, который гарантированно является последним, который выполняет функция. Примеры включают "для" циклов без условия и "if-else", заявления, в которых каждая половина заканчивается "возвратом". Если окончательный оператор функции может быть синтаксически показан как завершающий утверждение, никакое окончательное утверждение "return" не требуется.

Обратите внимание, что правило чисто синтаксическое: оно не обращает внимания на значений в коде и поэтому не требует сложного анализа.

Обновление: изменение обратно совместимо, но существующий код с излишние "возвратные" заявления и призывы к панике могут быть упрощены вручную. Такой код может быть идентифицирован go vet.

И проблема, о которой я упоминал, теперь закрыт статусом "Исправлено".