Перейти к содержимому
ГоМастер

Поиск по урокам

Найдите урок, курс, термин или раздел

Урок 11 из 25 ~15 мин +50 XP

Условия: if и else

До этого урока каждая наша программа шла сверху вниз и делала всё, что написано, без вопросов. Настоящие программы стоят на развилках: пароль подошёл или нет, хватает ли денег на карте, пустили ли в фильм. Условия в Go расставляют эти развилки: оператор if выполняет блок кода только когда условие истинно, а else держит наготове запасной путь. Разберём if, else и else if, логические операторы в условиях, переменную, объявленную прямо в заголовке if, и ошибки, на которых спотыкается почти каждый новичок.

Содержание урока · 11 разделов

Условия в 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] дело не доходит.

Таблица истинности для условий#

aba && ba || b!a
truetruetruetruefalse
truefalsefalsetruefalse
falsetruefalsetruetrue
falsefalsefalsefalsetrue

Что выведет код?

Прочитайте код и выберите, что он выведет:

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. Уберите лишнюю строку обратно.

Вывод

Запустите код, чтобы увидеть вывод.

Типичные ошибки: скобки, лишний else и не-булево условие#

Три ошибки встречаются так часто, что их стоит назвать поимённо.

Первая — лишний else. Если ветка if завершает работу — печатает вердикт или делает return, — else не нужен: после развилки всё равно ничего не исполняется, а каждая вложенная else добавляет отступ, то есть прямую трату внимания читателя.

Вторая — не-булево условие. В Go нет «истинных чисел»: if count при целом count не скомпилируется, ноль не считается ложью, пустая строка — тем более. Проверяют явно: if count > 0. Заодно это страхует от классической опечатки: if x = 5 не пройдёт, потому что присваивание не возвращает значения, — компилятор ловит то, что в C часто становится невидимым багом.

Третья вам уже знакома — else с новой строки: автоматическая точка с запятой после } отрезает ветку от if. Итого три коротких правила: без скобок вокруг условия, без else после завершающей ветки, } else { на одной строке.

Ранний выход вместо else

GO
package 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 программа должна напечатать «холодно». Три пропуска — по одному на каждое ключевое слово цепочки.

temp := 8 temp > 25 { fmt.Println("жарко") } temp > 15 { fmt.Println("тепло") } { fmt.Println("холодно") }

Соберите программу с переменной в if

Соберите программу: из temp вычитается пять, и переменная t, объявленная в заголовке if, решает, что печатать. Правильная программа выводит «жарко: 26».

Строки

Ваша программа

Нажимайте на строки слева, чтобы собрать программу

Карточки: условия и ветвление

Термин

Как выглядит заголовок if в Go?

нажмите, чтобы перевернуть
Определение

if условие { ... }: без круглых скобок вокруг условия, фигурные скобки обязательны даже для одной команды, а условие должно иметь тип bool.

1 / 6

Песочница урока

Редактируйте код и запускайте его прямо здесь — интерпретатор работает в браузере, ничего устанавливать не нужно. За каждый запуск — +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 Base · Условия: if и else)

Вопросы и ответы по уроку

Обязательны ли фигурные скобки, если в ветке одна команда?

Да, в Go не бывает if без блока: тело ветвления — всегда фигурные скобки, отступ их не заменяет. Это осознанное решение языка: одна из самых дорогих ошибок в истории — баг goto fail в iOS 2014 года — случилась в коде без скобок, где лишняя строка оказалась снаружи проверки и выполнялась всегда.

Чем else if отличается от вложенного if в else?

Только формой записи: else if — это if внутри else, прижатый в одну строку, чтобы цепочка читалась сверху вниз без лесенки отступов. Семантика одинаковая, но длинные вложенные else уезжают вправо и теряют читателей, поэтому цепочка — стандартный вид.

Можно ли объявить переменную в if через var, а не :=?

Можно: инициализирующий оператор — это обычный оператор, и var там допустим. Но := короче и не требует заранее придуманного типа, поэтому в заголовках if пишут почти всегда его. Правило одно для обоих вариантов: переменные видны только внутри всей конструкции if/else и не живут после неё.

Термины урока

Ключевые понятия из этого урока — короткие определения в глоссарии. Наведите на термин, чтобы вспомнить, откройте карточку для подробностей и ссылки на практику.

Следующая ступень учебного пути

Go Pro25 уроков~14 чпрактика25 уроков уже доступны

Продвинутые возможности Go: от замыканий до рефлексии

Продвинутый курс Go: замыкания, defer, горутины, каналы, контекст, интерфейсы, дженерики, рефлексия, тесты и JSON. 25 уроков с практикой в браузере.

  • Писать и читать конкурентный код: go-функции, каналы, select
  • Управлять жизненным циклом операций через context
  • Проектировать API на интерфейсах
  • Использовать дженерики без злоупотребления