Перейти к содержимому
Теория · Циклы · урок 5 из 8

range по числу

Пока бегун сам считает круги, он может сбиться: начать счёт не с того числа или пробежать лишний круг. На многих стадионах круги считает табло, и бегуну остаётся только бежать.

Цикл с тремя частями — это бегун, который считает сам. Чтобы повторить действие n раз, он держит счётчик, условие и шаг. Это три места, где можно ошибиться:

  • начать с единицы вместо нуля;
  • поставить <= вместо <;
  • забыть шаг.

Для такого повтора в Go есть короткая запись с ключевым словом range — это и есть табло:

GO
package main

import "fmt"

func main() {
    for i := range 5 {
        fmt.Print(i, " ") // 0 1 2 3 4
    }
}

Давайте посмотрим, что напечатала программа. Тело выполнилось пять раз, а i по очереди было 0, 1, 2, 3 и 4.

Две формы range по числу

У этой записи две формы: с переменной для номера итерации и без неё.

С переменной: for i := range n

Заголовок читается слева направо:

  • for — ключевое слово цикла;
  • i := объявляет переменную для номера итерации;
  • range n говорит, сколько итераций выполнить.

Цикл выполняет n итераций, а переменная i по очереди принимает значения от 0 до n - 1. Он делает то же, что for i := 0; i < n; i++, но Go сам ведёт счётчик и шаг. Значения 5 переменная i не принимает: последняя итерация идёт с i, равной 4.

Здесь табло отличается от настоящего: оно начинает счёт с нуля. Человек назовёт первый круг первым, а range — нулевым. Об этом стоит помнить каждый раз, когда номер итерации попадает в вычисления.

Вместо числа можно написать переменную или выражение типа int:

  • for i := range count выполняет тело count раз;
  • если значение равно нулю или отрицательное, тело не выполняется ни разу;
  • когда счёт идёт не с нуля или в обратную сторону, нужен цикл с тремя частями, например for i := 5; i >= 1; i--.

Без переменной: for range n

Когда номер итерации не нужен, переменную не объявляют вовсе. Запись for range 3 выполняет тело три раза:

GO
for range 3 {
    fmt.Print("Go ") // Go Go Go
}

Объявить i и не использовать её нельзя: неиспользуемая переменная — ошибка компиляции, и для цикла правило то же. Поэтому для повтора без номера пишут for range n без имени.

Инструкции break и continue работают в обеих формах так же, как в цикле с тремя частями.

Что изменилось в Go 1.22

Эта запись появилась в Go 1.22, поэтому в старых учебниках её нет. В той же версии изменились два правила:

  • появился range по целому числу;
  • каждая итерация любого цикла for получает собственную копию переменной цикла.

В программах этой темы разницы во втором правиле не видно, но об этом изменении часто спрашивают на собеседованиях.

Частая ошибка

Цикл по range 5 должен сложить числа от 1 до 5:

GO
s := 0
for i := range 5 { // ✗
    s += i
}
fmt.Println(s)

Программа печатает 10, а не 15: переменная i пробегает значения от 0 до 4, и пятёрка в сумму не попадает. Прибавляйте i + 1 или запишите цикл с тремя частями: for i := 1; i <= 5; i++.

Главное

  • for i := range n выполняет n итераций, и i принимает значения от 0 до n - 1.
  • При нулевом или отрицательном n тело не выполняется ни разу.
  • for range n повторяет тело n раз без переменной.
  • Для счёта не с нуля или в обратную сторону нужен цикл с тремя частями.

Подпишись, чтобы пройти курс

Курс бесплатный. Войди через Telegram и подпишись на канал — откроются все уроки.

Войти другим способом