💬 Какие особенности оператора break следует учитывать при использовании в сочетании со switch или select?
Рассмотрим пример. Мы используем
На первый взгляд код может казаться правильным, но он не приводит к выполнению ожидаемых действий. Оператор
💡
Как написать код, который будет прерывать цикл, а не действие оператора
☑️ Здесь мы связываем
Прерывание не того оператора также может произойти и в случае с
Здесь самым внутренним оператором из списка
Как и ожидалось,
Рассмотрим пример. Мы используем
switch
внутри for
. Когда индекс цикла получает значение 2
, требуется прервать цикл:for i := 0; i < 5; i++ {
fmt.Printf("%d ", i)
switch i {
default:
case 2: // Если i равен 2, то вызывается оператор break
break }
}
На первый взгляд код может казаться правильным, но он не приводит к выполнению ожидаемых действий. Оператор
break
не завершает цикл for
, он завершает действие оператора switch
. Следовательно, вместо итерации от 0
до 2
код выполняет итерацию от 0
до 4
: 0 1 2 3 4
.💡
break
завершает выполнение самого последнего оператора for
, switch
или select
. И здесь он прерывает действие switch
.Как написать код, который будет прерывать цикл, а не действие оператора
switch
? Самый идиоматический способ — использовать loop
:loop:
for i := 0; i < 5; i++ {
fmt.Printf("%d ", i)
switch i {
default:
case 2:
break loop // Прерывается цикл, привязанный к loop, а не к switch }
}
☑️ Здесь мы связываем
loop
с циклом for
. Поскольку мы указываем эту метку в операторе break
, то он прерывает цикл, а не действие оператора switch
. Новый код выведет 0 1 2
, как и требовалось.Прерывание не того оператора также может произойти и в случае с
select
, находящимся внутри цикла. В примере ниже мы хотим использовать select
с двумя case
и выйти из цикла, если контекст отменяется:for {
select {
case <-ch:
// Какие-то действия
case <-ctx.Done():
break // Цикл прерывается, если контекст отменяется
}
}
Здесь самым внутренним оператором из списка
for
, switch
, select
является select
, а не for
. Поэтому цикл продолжается. Чтобы прервать сам цикл, используем loop:loop:
for {
select {
case <-ch:
// Какие-то действия
case <-ctx.Done():
break loop // Прерывается выполнение привязанного к loop цикла, а не select
}
}
Как и ожидалось,
break
приводит к выходу из цикла, а не к прерыванию выполнения select
.