switch
В холле большого здания висит указатель: «Бухгалтерия — 3 этаж, отдел кадров — 5 этаж, столовая — 1 этаж». Вы не обходите все этажи по очереди, а находите в указателе свою строку и сразу едете на нужный этаж.
Цепочка else if похожа на обход этажей. Когда одну переменную сравнивают с несколькими значениями, цепочка повторяет одно и то же сравнение в каждой ветке. Инструкция switch работает как указатель в холле: вычисляет выражение один раз и выполняет ветку case с таким же значением:
package main
import "fmt"
func main() {
day := 6
switch day {
case 1, 2, 3, 4, 5:
fmt.Println("workday")
case 6, 7:
fmt.Println("weekend") // weekend
default:
fmt.Println("no such day")
}
}Давайте пройдём по программе:
switch dayвычисляетdayи получает6.case 1, 2, 3, 4, 5:— эти значения не подходят.case 6, 7:— шестёрка в списке есть, поэтому программа печатаетweekend.default:— до этой ветки дело не доходит.
Ветки case и default
В switch с выражением два вида веток.
case со значениями
Ветка case перечисляет значения, при которых она выполняется. Правила такие:
- несколько значений одного
caseперечисляют через запятую:case 6, 7:; - значения имеют тот же тип, что и выражение после
switch; - одно значение не может стоять в двух
case: компилятор сообщитduplicate case.
default
Ветка default выполняется, когда не подошёл ни один case. Если её нет, в этом случае не выполняется ничего.
Если функция возвращает значение из веток switch, компилятор требует ветку default или return после switch. Без них он сообщает missing return, даже когда условия покрывают все случаи.
Конец ветки
В разных языках ветка switch заканчивается по-разному. В Go есть два варианта.
Без break
После выполненной ветки switch сразу завершается, поэтому break в конце ветки не нужен. В C всё наоборот: без break выполнение проваливается в следующую ветку.
fallthrough
В Go проваливание включают явно, словом fallthrough в конце ветки:
level := 2
switch level {
case 2:
fmt.Print("admin ")
fallthrough
case 1:
fmt.Println("user") // admin user
}Разберём, что делает fallthrough:
- переходит в следующий
case, не проверяя его значение, поэтому приlevel == 2программа печатаетadmin user; - при
level == 1программа печатает толькоuser: веткаcase 2не выполнялась; fallthroughпишут последней инструкцией ветки, а в последней веткеswitchего писать нельзя: переходить некуда.
Нужен fallthrough редко: обычно хватает нескольких значений в одном case.
Этот вопрос часто задают на собеседовании: чем switch в Go отличается от switch в C? Главное в ответе: в Go ветка не проваливается в следующую сама, break не нужен, а проваливание включают словом fallthrough.
switch без выражения
Выражение после switch можно не писать. Тогда в каждом case стоит условие типа bool, и такой switch заменяет цепочку if и else if:
switch t := 25; {
case t < 0:
fmt.Println("frost")
case t < 30:
fmt.Println("mild") // mild
case t > 10:
fmt.Println("warm")
}Условия в case
Такой switch выполняет первую ветку с истинным условием. В примере условия t < 30 и t > 10 истинны оба, но программа печатает только mild. До case t > 10 дело не доходит.
Здесь указатель в холле перестаёт быть точной картинкой. В указателе каждому отделу соответствует одна строка, а условия в case могут быть верны сразу для нескольких строк. Тогда решает порядок: Go читает ветки сверху вниз и выполняет первую подходящую.
Инициализация
Как и в if, сразу после слова switch можно написать инициализацию — тогда после неё остаётся точка с запятой: switch t := 25; {.
- Переменная
tиз инициализации видна во всех ветках. - После
switchона исчезает, как уif. - Без инициализации пишут
switch {.
Частая ошибка
В switch без выражения широкое условие поставили выше узкого:
score := 95
switch {
case score >= 60: // ✗
fmt.Println("pass")
case score >= 90:
fmt.Println("excellent")
}Программа печатает pass: условие score >= 60 истинно для 95 и проверяется первым. Ветка score >= 90 не выполнится ни при каком score. Ставьте самое строгое условие первым: сначала score >= 90, затем score >= 60.
Главное
switchвычисляет выражение один раз и выполняетcaseс таким же значением, аdefault— когда не подошёл ни один.- После ветки
switchзавершается сам:breakне нужен, а проваливание включают словомfallthrough. switchбез выражения выполняет первую ветку с истинным условием.- Поэтому в таком
switchсамое строгое условие ставят первым.
Подпишись, чтобы пройти курс
Курс бесплатный. Войди через Telegram и подпишись на канал — откроются все уроки.