Подробная механика работы цикла for: порядок выполнения и отладка

Порядок выполнения компонентов цикла

При запуске цикла for компоненты выполняются в строгом порядке:

Шаг 1: Инициализация (init) — выполняется один раз перед началом цикла

for i := 1; i <= 5; i++ {
    // ↑ инициализация: i := 1 (выполняется один раз)
}

Шаг 2: Проверка условия (condition) — выполняется перед каждой итерацией

for i := 1; i <= 5; i++ {
    //        ↑ проверка: i <= 5 перед входом в тело
}

Шаг 3: Выполнение тела цикла — если условие истинно

for i := 1; i <= 5; i++ {
    fmt.Println(i)  // ← тело цикла
}

Шаг 4: Постусловие (post) — выполняется после каждой итерации

for i := 1; i <= 5; i++ {
    //                ↑ приращение: i++ после тела
}

Шаг 5: Возврат к шагу 2 — снова проверка условия

Пример с остановом при i <= 0

for i := 1; i <= 0; i++ {
    fmt.Println(i)
}
// Порядок: init (i=1) → condition (1<=0 = false) → цикл не выполнится

Условие 1 <= 0 ложно, поэтому тело цикла ни разу не выполняется.

Пример с остановом при i <= 1

for i := 1; i <= 1; i++ {
    fmt.Println(i)
}
// Порядок:
// 1. init: i=1
// 2. condition: 1<=1 = true → вход в тело
// 3. body: печать "1"
// 4. post: i++ (теперь i=2)
// 5. condition: 2<=1 = false → выход из цикла

Цикл выполнится один раз, напечатает 1, затем завершится.


Область видимости счётчика

Счётчик внутри for

Переменная, объявленная в init, видна только внутри цикла:

for i := 10; i <= 12; i++ {
    fmt.Printf("i = %d (видна здесь)\n", i)
}
// fmt.Println(i)  // ❌ ошибка: undefined: i

Счётчик снаружи for

Если объявить переменную до цикла, она доступна везде:

index := 1
fmt.Println("До цикла:", index)  // 1

for ; index <= 1; index++ {
    fmt.Println("Внутри:", index)  // 1
}

fmt.Println("После цикла:", index)  // 2

Порядок:

  1. index = 1 (до цикла)
  2. Проверка: 1 <= 1 → истина
  3. Печать “Внутри: 1”
  4. Приращение: index++index = 2
  5. Проверка: 2 <= 1 → ложь → выход
  6. Печать “После цикла: 2”

Работа с дебаггером в VS Code

Подготовка проекта

Шаг 1: Инициализация модуля

go mod init example.com/loops

Шаг 2: Установка точки останова (breakpoint)

Кликните слева от номера строки — появится красная точка:

sum := 0  // ← поставьте точку останова здесь
for i := 1; i <= 10; i++ {
    sum += i
}

Шаг 3: Запуск отладки

  • Откройте панель Run and Debug (Ctrl+Shift+D)
  • Нажмите “Run and Debug”
  • Выберите “Go”

Пошаговое выполнение (Step Over)

Step Over (F10) — выполнить текущую строку и перейти к следующей.

Пример отладки суммы 1+2+3:

sum := 0              // ← точка останова
for i := 1; i <= 3; i++ {
    sum += i
}
fmt.Println("Сумма:", sum)

Пошаговая трассировка:

Шаг Строка Действие sum i Описание
1 sum := 0 Инициализация 0 Переменная создана
2 for i := 1 Init цикла 0 1 Счётчик создан
3 i <= 3 Проверка условия 0 1 1<=3 = true
4 sum += i Тело цикла 1 1 0+1=1
5 i++ Post 1 2 Приращение
6 i <= 3 Проверка условия 1 2 2<=3 = true
7 sum += i Тело цикла 3 2 1+2=3
8 i++ Post 3 3 Приращение
9 i <= 3 Проверка условия 3 3 3<=3 = true
10 sum += i Тело цикла 6 3 3+3=6
11 i++ Post 6 4 Приращение
12 i <= 3 Проверка условия 6 4 4<=3 = false → выход
13 fmt.Println Печать 6 Вывод “Сумма: 6”

Просмотр переменных

В панели VariablesLocal отображаются текущие значения:

sum: 0
i: 1

На каждом шаге значения обновляются.


Вложенные циклы: таблица умножения

Код

for i := 1; i <= 3; i++ {
    for j := 1; j <= 3; j++ {
        product := i * j
        fmt.Printf("%d*%d=%d  ", i, j, product)
    }
    fmt.Println()
}

Трассировка выполнения

Итерация 1 внешнего цикла (i=1):

Шаг i j product Вывод
1 1 1 1 1*1=1
2 1 2 2 1*2=2
3 1 3 3 1*3=3
4 1 Перевод строки

Итерация 2 внешнего цикла (i=2):

Шаг i j product Вывод
5 2 1 2 2*1=2
6 2 2 4 2*2=4
7 2 3 6 2*3=6
8 2 Перевод строки

Итерация 3 внешнего цикла (i=3):

Шаг i j product Вывод
9 3 1 3 3*1=3
10 3 2 6 3*2=6
11 3 3 9 3*3=9
12 3 Перевод строки

Порядок выполнения вложенных циклов:

  1. Внешний цикл инициализирует i=1
  2. Внутренний цикл выполняется полностью (j=1, 2, 3)
  3. Внешний цикл увеличивает i=2
  4. Внутренний цикл снова выполняется полностью (j=1, 2, 3)
  5. И так далее

Практический пример: сумма первых N чисел

Задача

Найти сумму чисел от 1 до 10.

Решение через цикл

sum := 0
for i := 1; i <= 10; i++ {
    sum += i
    fmt.Printf("i=%d, sum=%d\n", i, sum)
}
fmt.Printf("Итого: %d\n", sum)

Вывод:

i=1, sum=1
i=2, sum=3
i=3, sum=6
i=4, sum=10
i=5, sum=15
i=6, sum=21
i=7, sum=28
i=8, sum=36
i=9, sum=45
i=10, sum=55
Итого: 55

Проверка правильности

Математическая формула: ( \text{sum} = \frac{n \times (n+1)}{2} )

Для ( n = 10 ): ( \frac{10 \times 11}{2} = \frac{110}{2} = 55 ) ✅


Примеры с условиями внутри циклов

Чётные числа от 1 до 10

fmt.Println("Чётные числа от 1 до 10:")
for i := 1; i <= 10; i++ {
    if i%2 == 0 {
        fmt.Printf("%d ", i)
    }
}

Вывод: 2 4 6 8 10

Средняя оценка из случайных чисел

totalScore := 0
count := 5

fmt.Println("5 случайных оценок (1-100):")
for i := 1; i <= count; i++ {
    score := rand.Intn(100) + 1
    totalScore += score
    fmt.Printf("Оценка %d: %d\n", i, score)
}

average := totalScore / count
fmt.Printf("Среднее: %d\n", average)

Пример вывода:

5 случайных оценок (1-100):
Оценка 1: 73
Оценка 2: 45
Оценка 3: 89
Оценка 4: 12
Оценка 5: 67
Среднее: 57

Рекомендации по отладке

1. Используйте дебаггер для сложных циклов

Особенно для вложенных циклов — ставьте точки останова и смотрите изменение переменных пошагово.

2. Проверяйте ожидаемый результат

Перед запуском подумайте: «Что должно получиться?». Например, сумма 1+2+…+10 = 55.

3. Печатайте промежуточные значения

for i := 1; i <= 3; i++ {
    fmt.Printf("Итерация %d, i=%d\n", i, i)
}

4. Изучайте паттерны

  • Счётчик вверх: i++ с условием i <= N
  • Счётчик вниз: i-- с условием i >= 1
  • Шаг больше 1: i += 2 для чётных/нечётных

Ключевые моменты

  1. Порядок: init (1 раз) → condition → body → post → condition → …
  2. Init выполняется один раз перед началом цикла
  3. Condition проверяется перед каждой итерацией
  4. Post выполняется после каждой итерации
  5. Область видимости: счётчик из init виден только в цикле
  6. Вложенные циклы: внутренний полностью завершается перед следующей итерацией внешнего
  7. Дебаггер: Step Over (F10) для пошагового выполнения
  8. Проверка: считайте ожидаемый результат до запуска
  9. Вариации: можно опускать init/post (использовать внешние переменные)
  10. Практика: решайте задачи пошагово с дебаггером для понимания