Урок курса
Цикл for: три формы, break и continue
Golang с нуляВ прошлом уроке мы разбирали if и switch — инструменты для ветвления. Теперь добавим повторение: for в Go — единственный цикл, но он достаточно гибок, чтобы заменить и while, и бесконечный цикл с флагом выхода.
Три формы цикла for: синтаксис и механизм выполнения
Go не имеет while или do-while — только for. Зато у него три формы записи, и каждая уместна в своей ситуации.
Форма с инициализатором, условием и постшагом — то, что в других языках называют классическим for:
for i := 0; i < 5; i++ {
fmt.Println(i)
}
Порядок выполнения фиксирован: сначала один раз выполняется инициализатор i := 0, затем перед каждой итерацией проверяется условие i < 5, и только если оно истинно — выполняется тело. После тела — постшаг i++, и снова проверка условия. Когда условие становится ложным, цикл завершается.
Важная деталь: переменная i, объявленная через := в инициализаторе, существует только внутри цикла. За его пределами она недоступна. Это не ограничение, а разумная область видимости — счётчик цикла редко нужен после его завершения.
Ещё одна особенность Go: i++ — это инструкция, а не выражение. Написать j := i++ не получится — компилятор откажет. Это сделано намеренно, чтобы устранить целый класс ошибок вроде a[i++] = i++.
Форма только с условием — аналог while:
n := 1
for n < 100 {
n *= 2
}
fmt.Println(n) // 128
Здесь нет инициализатора и постшага — только условие. Переменная n объявлена до цикла, потому что её значение нужно после выхода.
Бесконечный цикл — форма вообще без условия:
for {
// выполняется бесконечно
}
Выйти из него можно только явно: через break, return или в экстремальных случаях os.Exit. Именно эта форма удобна, когда условие выхода проверяется не в заголовке цикла, а где-то в середине тела — что и понадобится в итоговом примере урока.
Во всех трёх формах тело цикла обязательно заключено в фигурные скобки — без исключений, как и в if.
break и continue: досрочный выход и пропуск итерации
break и continue управляют ходом выполнения цикла, но делают это по-разному.
break немедленно завершает ближайшую охватывающую конструкцию — это может быть for, switch или select. Важно: если break стоит внутри switch, вложенного в цикл, он завершит switch, а не цикл. Мы разбирали switch в прошлом уроке — теперь это различие становится практически значимым.
continue, в отличие от break, относится только к циклу — к ближайшему охватывающему for. Он прерывает текущую итерацию и переходит к следующей. Но «следующая итерация» — это не просто начало тела. В форме с постшагом for i := 0; i < n; i++ после continue сначала выполняется i++, и только затем проверяется условие. Это принципиально.
for i := 0; i < 5; i++ {
if i == 2 {
continue
}
fmt.Println(i)
}
Вывод:
0 1 3 4
Когда i равно 2, continue пропускает fmt.Println, но i++ всё равно выполняется — поэтому следующая итерация начнётся с i = 3, а не зависнет на i = 2. Цикл не стал бесконечным.
for i := 0; i < 5; i++ {
if i == 3 {
break
}
fmt.Println(i)
}
Вывод:
0 1 2
Как только i достигает 3, цикл завершается полностью — постшаг не выполняется, условие не проверяется.
Если циклы вложены, оба оператора без метки действуют на внутренний цикл — тот, в теле которого они стоят. Внешний цикл продолжается. Это отдельно от ситуации со switch: break внутри switch всегда завершает switch, даже если снаружи есть цикл — на цикл такой break не влияет.
Бесконечный цикл с break: суммирование чисел до ввода 0
Соберём всё вместе в задаче: читать числа с клавиатуры и накапливать их сумму, пока пользователь не введёт 0.
package main
import "fmt"
func main() {
var sum, n int
for {
fmt.Scan(&n)
if n == 0 {
break
}
sum += n
}
fmt.Println(sum)
}
Пример работы:
3 7 -2 0 8
Обе переменные объявлены до цикла через var sum, n int, но по разным причинам.
sum — накопитель, и его объявление снаружи обязательно по двум причинам. Первая: значение должно сохраняться между итерациями. Если написать sum := 0 внутри тела цикла, на каждой итерации создаётся новая переменная с нулевым начальным значением — всё накопленное за предыдущие итерации теряется. Вторая: sum нужна после завершения цикла — в строке fmt.Println(sum). Переменная, объявленная через := внутри тела for, недоступна за его пределами; программа с sum внутри цикла попросту не скомпилировалась бы.
n — другой случай. fmt.Scan(&n) принимает адрес переменной, но само по себе это не требует объявлять n вне цикла — var n int или n := 0 внутри тела тоже допустимы синтаксически. Внешнее объявление здесь — вопрос удобства: переменная повторно используется на каждой итерации без лишних объявлений.
Почему выбрана бесконечная форма for, а не for n != 0? Потому что условие выхода проверяется уже после чтения нового значения n, то есть в середине тела. Форма только с условием потребовала бы либо читать первое число до цикла, либо дублировать логику. Бесконечный for с break внутри выражает намерение прямее: «читай до тех пор, пока сам не решишь остановиться».
Задача 1
Что выведет следующая программа?
package main
import "fmt"
func main() {
sum := 0
for i := 1; i <= 5; i++ {
if i == 3 {
continue
}
sum += i
}
fmt.Println(sum)
}
Задача 2
Что произойдёт при компиляции программы?
package main
import "fmt"
func main() {
for i := 0; i < 3; i++ {
count := 0
count += i
}
fmt.Println(count)
}
Задача 3
Что выведет следующая программа? Введите строки вывода через пробел (например: 1 2 3).
package main
import "fmt"
func main() {
i := 1
for i <= 4 {
fmt.Println(i)
i++
}
}
Задача 4
Касса ярмарки
На городской ярмарке продавец пробивает товары один за другим, называя их цену. Каждая введённая сумма сразу учитывается в итоге, а когда все покупки оформлены, продавец вводит ноль — сигнал о том, что чек завершён.
Иногда в спешке в поле попадает случайная опечатка в виде отрицательного числа. Такие значения не должны портить результат, поэтому они молча игнорируются и на итог не влияют. Только корректные положительные суммы формируют окончательный счёт.
В конце программа выводит суммарную стоимость всех корректно введённых позиций. Если ни одна цена не оказалась положительной, итог будет равен нулю.
Формат ввода
Целые числа — цены покупок. Они могут быть записаны через пробел или с новой строки. Ввод всегда содержит завершающий 0; значения после него учитывать не нужно.
Формат вывода
Выведите одно целое число — сумму всех положительных цен до первого нуля. Отрицательные значения пропускайте.
Пример
Ввод: 120 80 -20 50 0 Вывод: 250
Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.
Отправьте решение, чтобы увидеть результаты тестов.
Задача 5
Зачётные круги на дорожке
На стадионе действует простое, но строгое правило учёта: не каждый пробежанный круг идёт в зачёт. Тренер давно установил, что чётные круги служат разминкой и восстановлением — они нужны организму, но в итоговый протокол не попадают. Только нечётные круги считаются полноценной нагрузкой и фиксируются как зачтённые.
Бегун, завершив тренировку, знает одно число — сколько кругов он сделал суммарно. Именно это число он и передаёт для подсчёта. Задача состоит в том, чтобы по общему количеству кругов определить, сколько из них попали в итоговый протокол, то есть сколько среди них нечётных по номеру.
Программа должна принять это единственное число и вернуть ответ: итоговое количество зачтённых кругов. Если бегун не сделал ни одного круга, результат очевиден — в протоколе значится ноль.
Что нужно сделать
Считайте неотрицательное целое totalLaps. Используйте полную форму цикла for с переменной номера круга от 1 до totalLaps включительно. Чётные номера пропускайте через continue, а нечётные увеличивайте счётчик. После цикла выведите только количество зачётных кругов.
Формат ввода
Одно неотрицательное целое число — общее количество кругов.
Формат вывода
Одно целое число — количество нечётных номеров от 1 до totalLaps.
Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.
Отправьте решение, чтобы увидеть результаты тестов.
Задачи к уроку
- Go for и continue: пропуск чётных чисел в цикле
Пройдите номера кругов циклом for, пропустите чётные через continue и подсчитайте нечётные.
Продолжить с сохранением прогресса
Перейдите к уроку в учебном кабинете.
