В обработчике условие справа вызывает функцию с побочным эффектом: в каком случае Go вообще не вычислит этот операнд?
Go использует ленивое вычисление логических выражений. В выражении с && правый операнд не вычисляется, если левый дал false; в выражении с || он не вычисляется, если левый дал true.
Поэтому функция справа может не выполниться вовсе, а её побочный эффект не произойдёт.
Короткое замыкание вычислений появилось как практический приём для безопасного составления условий: сначала проверяется защитное условие, а потенциально опасная или дорогая операция выполняется только при необходимости.
В Go это часть семантики операторов && и ||, а не случайная оптимизация компилятора. Программа должна сохранять такое поведение даже при оптимизации.
Если разработчик рассчитывает, что оба операнда логического выражения выполнятся, он может потерять побочный эффект: запись в журнал, изменение счётчика, обновление состояния или вызов проверки.
Одновременно короткое замыкание позволяет безопасно поставить предварительную проверку перед операцией, которая может быть некорректной без неё. Неверная перестановка условий способна привести к панике или лишней работе.
Операнды вычисляются слева направо. Для A && B сначала вычисляется A: если результат false, итог уже известен, поэтому B пропускается. Если A равен true, вычисляется B.
Для A || B сначала вычисляется A: при true правый операнд не нужен, а при false вычисляется B. Оба оператора работают только со значениями типа bool и возвращают bool.
В примере check не вызывается, потому что ready равно false. Если функция не имеет побочных эффектов, пропуск обычно влияет только на производительность; если имеет — он становится наблюдаемым поведением.
Порядок условий важен. Защитную проверку следует ставить слева: например, сначала проверять наличие ресурса, а затем обращаться к нему. Замена && или || на побитовые операторы не является эквивалентом: у них другая семантика и другие требования к типам.
В HTTP-обработчике проверяют авторизацию и затем вызывают проверку прав. Вариант с authorized && hasPermission() не вызывает проверку прав для неавторизованного запроса, что экономит работу и не раскрывает лишние детали.
Можно было бы сначала вызвать обе функции, а затем объединить результаты. Такой вариант проще только при отсутствии зависимости между проверками, но он выполняет ненужную работу и может запускать побочные эффекты для запроса, который уже отклонён.
Выбранное короткое замыкание сохраняет порядок защиты, уменьшает число вызовов и делает условие непосредственно отражающим логику допуска. При этом функции, используемые в таких выражениях, лучше по возможности делать без побочных эффектов.
&& и ||?Да. Левый операнд вычисляется первым. Правый вычисляется только тогда, когда без него невозможно определить результат всего выражения. Это гарантированное правило семантики операторов, поэтому зависеть от него в защитных условиях допустимо.
bool?Нет. В Go нет автоматического преобразования чисел, указателей или других значений в логический тип. Операнды && и || должны быть логическими выражениями; для проверки указателя или другого значения нужна явная проверка, предусмотренная его типом.
Нужно вызвать их отдельными инструкциями, сохранив результаты в переменных, а затем объединить эти результаты. Использование && или || в одном выражении намеренно допускает пропуск правой части, поэтому оно не подходит, если обязательны оба вызова или оба побочных эффекта.