Содержание урока · 11 разделов
- Условия в go: как устроен оператор if
- If else go: развилка на две дороги
- Else if: цепочка проверок
- Логические операторы в условиях: и, или, не
- Таблица истинности для условий
- Переменная в if: инициализирующий оператор и область видимости
- Типичные ошибки: скобки, лишний else и не-булево условие
- Ранние возвраты против вложенности
- Песочница урока
- Коротко: что запомнить
- Вопросы и ответы
Условия в go: как устроен оператор if#
Развилка начинается с вопроса, на который есть ровно два ответа — да или нет. Такой вопрос записывается булевым выражением: строить их мы научились в уроке про bool и логику — сравнения age >= 18, password == "secret", balance <= 0 дают true или false. Оператор if берёт выражение и выполняет свой блок только при true; при false блок молча пропускается, и программа едет дальше по прямой.
Запись лаконичная: if age >= 18 { fmt.Println("проходите") }. Круглые скобки вокруг условия в Go не пишут: компилятор их стерпит, но gofmt, стандартный форматировщик, молча их удалит, и весь идиоматичный код живёт без них. Зато фигурные скобки обязательны всегда, даже если в блоке одна строка. И деталь на будущее: отступы — только для людей, компилятор смотрит исключительно на скобки.
Песочница: первая развилка
Запустите: 14 > 20 ложно, сработал else. Поменяйте temp на 25 — теперь условие истинно и печатается первая строка. Затем допишите после else ещё один независимый if: `if temp < 0 { fmt.Println("лёд на дороге") }` и подберите значение temp, при котором напечатаются и подсказка про куртку, и предупреждение про лёд.
Запустите код, чтобы увидеть вывод.
If else go: развилка на две дороги#
Пара, которую ищут по запросу «if else go», — это две дороги, из которых выполняется ровно одна. Ветка else не имеет собственного условия: она срабатывает во всех остальных случаях, когда проверка if дала false. Гарантия «что-то одно, но что-то обязательно» — главное свойство развилки: если в блоке else увеличивать счётчик неудачных попыток, он не задвоится ни при каком раскладе.
У else есть синтаксическая странность, о которую спотыкается каждый второй: слово else обязано стоять на той же строке, где закрывающая скобка if. Перенесёте его на следующую строку — получите ошибку про неожиданный else, причём винить захочется строку с else, а виновата строка выше: Go сам вставляет точку с запятой в конец строки после } и отрезает else от его if. Песочница ругается точно так же. Правило короткое: } else { — одна строка.
Проверьте себя: заголовок ветвления
Переменная x уже объявлена. Как правильно записать заголовок ветвления в Go?
Else if: цепочка проверок#
Двух дорог часто мало: оценка превращается в пять слов, температура — в диапазон «жарко, тепло, прохладно, холодно». Для лестницы проверок есть else if: условия перебираются сверху вниз, и первая же истинная ветка выполняется, а все нижние пропускаются — даже если их условия тоже истинны. Финальный else без условия необязателен: он ловит «всё остальное» и спасает, когда ни одна проверка не выстрелила.
Отсюда правило, которое экономит часы отладки: от самого строгого условия — к самому мягкому. Поставьте проверку на 70 выше проверки на 90, и отличник с результатом 95 навсегда станет «хорошим»: до второй ветки очередь не доходит. В песочнице ниже это видно без слов.
Песочница: ведомость с оценками
Запустите: 74 попадает в ветку «хорошо», до остальных проверок дело не доходит. Прогоните score = 95, 50 и 3. А теперь поменяйте ветки местами — поставьте проверку score >= 70 первой — и запустите с score = 95: отличник превратится в «хорошо», хотя вторая ветка тоже истинна. Первая победившая проверка обрывает цепочку.
Запустите код, чтобы увидеть вывод.
Логические операторы в условиях: и, или, не#
Одно сравнение редко решает судьбу ветки: возраст подходит «и» билет куплен, день выходной «или» праздник, доступ запрещён, когда «не» админ. Условия собирают из булевой арифметики, которую мы разбирали в уроке про bool и логику: && требует истинности обоих операндов, || — хотя бы одного, ! переворачивает значение. Диапазон «от 18 до 35» записывается парой сравнений через &&: age >= 18 && age <= 35 — арифметическую запись 18 <= age <= 35 Go не примет, каждое сравнение надо проговаривать целиком.
Приоритеты операторов из урока про операторы и выражения работают и здесь: && связывает крепче ||, поэтому a || b && c читается как a || (b && c). Сомневаетесь — ставьте скобки: внутри условия они разрешены, запрет касается только внешних скобок вокруг всего выражения. Плюс сокращённые вычисления: если левая часть && уже ложна, правую Go даже не вычисляет. На этом строятся безопасные проверки вроде len(parts) > 0 && parts[0] == "Аня": у пустого среза левая половина ложна, и до обращения parts[0] дело не доходит.
Таблица истинности для условий#
| a | b | a && b | a || b | !a |
|---|---|---|---|---|
| true | true | true | true | false |
| true | false | false | true | false |
| false | true | false | true | true |
| false | false | false | false | true |
Что выведет код?
Прочитайте код и выберите, что он выведет:
package main
import "fmt"
func main() {
age := 16
ticket := false
if age >= 12 && ticket {
fmt.Println("проход в зал")
}
if age < 12 || ticket {
fmt.Println("льгота")
}
if !(age < 12) {
fmt.Println("взрослый билет")
}
}Переменная в if: инициализирующий оператор и область видимости#
В уроке про ввод данных мы видели проверку ошибки if err != nil. На практике она почти всегда выглядит иначе: if n, err := strconv.Atoi(s); err != nil. Между if и условием через точку с запятой можно вписать инициализирующий оператор — обычно короткое объявление :=. Он выполняется до проверки условия, а объявленные переменные живут ровно внутри конструкции: доступны в блоке if, в ветках else if и else — и исчезают сразу после закрывающей скобки.
Это не украшение, а способ держать переменные при их деле. n и err нужны только чтобы решить судьбу числа, — значит, им и место внутри if. Попытка напечатать n после конструкции закончится ошибкой undefined: n — за пределами развилки такой переменной нет, и это хорошо: меньше шансов случайно взять устаревшее значение. Оператор работает и без ошибок в придачу: if t := temp - 5; t >= 25 { ... }. А если значение нужно в нескольких местах ниже по коду, объявляйте его обычным := — тонкости обоих способов разбирались в уроке про переменные и константы.
Песочница: переменная внутри развилки
Запустите: из двух слов собрался разбор «имя и возраст». Замените input на "Аня" — сработает else со счётом слов. А теперь допишите после конструкции строку `fmt.Println(parts[0])` и запустите: песочница откажется так же, как настоящий компилятор, — parts не определена за пределами if. Уберите лишнюю строку обратно.
Запустите код, чтобы увидеть вывод.
Чем короче живёт переменная, тем меньше мест, где её можно случайно испортить или забыть, зачем она. Значение нужно для одного решения — объявляйте его в if; нужно в трёх местах ниже — обычным := на уровне функции. Я почти никогда не оставляю n и err из разбора ввода жить дальше проверки ошибки: пока переменная заперта в if, её актуальность гарантирована всей конструкцией.
Типичные ошибки: скобки, лишний else и не-булево условие#
Три ошибки встречаются так часто, что их стоит назвать поимённо.
Первая — лишний else. Если ветка if завершает работу — печатает вердикт или делает return, — else не нужен: после развилки всё равно ничего не исполняется, а каждая вложенная else добавляет отступ, то есть прямую трату внимания читателя.
Вторая — не-булево условие. В Go нет «истинных чисел»: if count при целом count не скомпилируется, ноль не считается ложью, пустая строка — тем более. Проверяют явно: if count > 0. Заодно это страхует от классической опечатки: if x = 5 не пройдёт, потому что присваивание не возвращает значения, — компилятор ловит то, что в C часто становится невидимым багом.
Третья вам уже знакома — else с новой строки: автоматическая точка с запятой после } отрезает ветку от if. Итого три коротких правила: без скобок вокруг условия, без else после завершающей ветки, } else { на одной строке.
Ранний выход вместо else
GOpackage main
import "fmt"
func main() {
password := "qwerty"
if password != "secret" {
fmt.Println("доступ запрещён")
return
}
fmt.Println("добро пожаловать")
}return завершает main: если пароль не подошёл, до строки с приветствием дело не доходит. Проверка плохого случая стоит первой и убирается с дороги, а главный путь — печатать приветствие — остаётся прижатым к левому краю без единого else. Пока мы пишем только main, эффект скромный, но когда дойдём до функций, этот приём вырастет в guard clause — «условие-страж», стандартный способ держать вложенность на глубине одного if.
Ранние возвраты против вложенности#
Когда проверок несколько и каждая зависит от предыдущей, код легко уезжает вправо: if внутри if внутри else — три отступа, и уже непонятно, какой if чьё условие охраняет. Лекарство то же — ранний выход: плохие случаи проверяются первыми и сразу завершают работу, основной путь остаётся прямым. Внутри main для этого служит return, как в примере выше; в будущих функциях он же вернёт значение вызывающему коду.
Моё правило простое: если тело if заканчивается return, else не нужен, — и я рад, что линтеры в большинстве команд проверяют это автоматически. Спорить можно об одном: в короткой паре «если/иначе» с двумя симметричными действиями else читается нормально, вырывать его насильно не стоит.
И последнее: если одна переменная сравнивается с пачкой значений, длинная лестница else if — не лучший выбор. Для этого в Go есть switch — тема следующего урока про множественный выбор.
Вставьте ключевые слова
Соберите цепочку из трёх веток: при temp 8 программа должна напечатать «холодно». Три пропуска — по одному на каждое ключевое слово цепочки.
Соберите программу с переменной в if
Соберите программу: из temp вычитается пять, и переменная t, объявленная в заголовке if, решает, что печатать. Правильная программа выводит «жарко: 26».
Строки
Ваша программа
Нажимайте на строки слева, чтобы собрать программу
Карточки: условия и ветвление
Песочница урока
Редактируйте код и запускайте его прямо здесь — интерпретатор работает в браузере, ничего устанавливать не нужно. За каждый запуск — +2 XP.
Запустите код, чтобы увидеть вывод.
Коротко: что запомнить
- if выполняет блок только при истинном условии; условие — bool, без круглых скобок, фигурные скобки обязательны.
- else — запасная ветка без своего условия; слово else ставится на строку закрывающей скобки: } else {.
- else if строит цепочку: первая истинная проверка побеждает, поэтому условия идут от строгого к мягкому.
- В условиях && требует истинности обоих операндов, || — хотя бы одного, ! переворачивает значение.
- Инициализирующий оператор if n, err := f(); err != nil объявляет переменные только для конструкции if.
- Переменные из if-инициализации не видны после if — это защита от лишних зависимостей, а не недоработка.
- Ранний возврат вместо else: проверь плохой случай и уходи, основной путь остаётся без вложенности.
Домашнее задание
Соберите кассу кинотеатра: price := 250 и age := 15. Правила: возраст до 12 включительно или от 65 — половина цены (price/2); от 13 до 18 — цена без пятой части (price - price/5); остальным — полная. Уложитесь в одну цепочку if/else if/else с операторами || и && и печатайте «цена: N». Проверьте три возраста: 15 (ожидайте 200), 70 (125) и 30 (250). Затем перепишите решение с ранними возвратами: каждый льготный случай печатает цену и сразу делает return — else в программе остаться не должно.
Личные заметкиПусто
Вопросы и ответы по уроку
Обязательны ли фигурные скобки, если в ветке одна команда?
Да, в Go не бывает if без блока: тело ветвления — всегда фигурные скобки, отступ их не заменяет. Это осознанное решение языка: одна из самых дорогих ошибок в истории — баг goto fail в iOS 2014 года — случилась в коде без скобок, где лишняя строка оказалась снаружи проверки и выполнялась всегда.
Чем else if отличается от вложенного if в else?
Только формой записи: else if — это if внутри else, прижатый в одну строку, чтобы цепочка читалась сверху вниз без лесенки отступов. Семантика одинаковая, но длинные вложенные else уезжают вправо и теряют читателей, поэтому цепочка — стандартный вид.
Можно ли объявить переменную в if через var, а не :=?
Можно: инициализирующий оператор — это обычный оператор, и var там допустим. Но := короче и не требует заранее придуманного типа, поэтому в заголовках if пишут почти всегда его. Правило одно для обоих вариантов: переменные видны только внутри всей конструкции if/else и не живут после неё.
Термины урока
Ключевые понятия из этого урока — короткие определения в глоссарии. Наведите на термин, чтобы вспомнить, откройте карточку для подробностей и ссылки на практику.
Изучайте дальше
Следующая ступень учебного пути
Продвинутые возможности Go: от замыканий до рефлексии
Продвинутый курс Go: замыкания, defer, горутины, каналы, контекст, интерфейсы, дженерики, рефлексия, тесты и JSON. 25 уроков с практикой в браузере.
- Писать и читать конкурентный код: go-функции, каналы, select
- Управлять жизненным циклом операций через context
- Проектировать API на интерфейсах
- Использовать дженерики без злоупотребления