Введение

В отличие от многих других языков программирования, в Go для организации циклов используется только одно ключевое слово — for. Несмотря на это, данный инструмент крайне эффективен и гибок. Давайте изучим особенности работы с циклом for в Go.

Основные темы:

  • Цикл For
  • Итерация по диапазону (For range)

Символы в строке

В предыдущем разделе, посвященном базовым структурам данных, мы узнали, что строка представляет собой набор символов. Следовательно, мы можем использовать индекс для получения конкретных символов в строке. Давайте создадим файл string.go и запишем в него следующий код:

cd ~/project
touch string.go
package main

import "fmt"

func main() {
    s := "labex"

    // Доступ к каждому символу строки по индексу
    fmt.Println(s[0], s[1], s[2], s[3], s[4])
    // Вывод символов
    fmt.Printf("%c %c %c %c %c\n", s[0], s[1], s[2], s[3], s[4])
}

Запустите программу:

go run string.go

Результат будет следующим:

108 97 98 101 120
l a b e x

В этой программе мы объявили строковую переменную для хранения значения "labex" и использовали индексы для доступа к каждому символу. При выводе первой строкой мы видим числа вместо самих букв.

Если сравнить эти числа с таблицей ASCII, станет ясно, что они соответствуют конкретным символам. Например, числу 108 соответствует латинская буква "l".

Это происходит потому, что символы фактически хранятся в виде числовых кодов в кодировке UTF-8. Поскольку UTF-8 обратно совместима с ASCII, позиция символа "l" содержит числовое значение 108.

Чтобы вывести именно символы, мы используем функцию fmt.Printf со спецификатором %c. Это продемонстрировано во второй строке вывода: программа преобразует числовой код обратно в графический символ.

Однако обращаться к каждому символу строки вручную через индекс неудобно, особенно если данных сотни или тысячи. В таких случаях для автоматизации процесса логично использовать цикл for.

Синтаксис цикла For

Цикл выполняет блок кода до тех пор, пока соблюдается определенное условие. Рассмотрим синтаксис оператора for:

for initialization; condition; post {
    // блок кода
}
  • Инициализация (initialization): выполняется один раз перед началом цикла (обычно здесь объявляется счетчик).
  • Условие (condition): проверяется перед каждой итерацией. Если оно истинно (true), цикл продолжается.
  • Пост-условие (post): выполняется в конце каждой итерации (обычно здесь изменяется значение счетчика).

Рассмотрим конкретный пример. Создайте файл for.go в директории ~/project со следующим содержимым:

cd ~/project
touch for.go
package main

import "fmt"

func main() {
    // Вывод чисел от 0 до 9
    for i := 0; i < 10; i++ {
        fmt.Println(i)
    }
}

Запустите программу:

go run for.go

Вывод:

0
1
2
3
4
5
6
7
8
9

В этой программе мы инициализируем временную переменную i значением 0. На каждой итерации значение i увеличивается на 1. Цикл продолжается, пока i меньше 10.

Обратите внимание: В цикле for блоки инициализации, условия и пост-условия являются необязательными.

Если оставить только условие, цикл for будет работать аналогично циклу while в других языках программирования.

Следующий код использует только условие для достижения того же результата:

package main

import "fmt"

func main() {
    i := 0
    for i < 10 {
        fmt.Println(i)
        i++
    }
}

Заметьте, что когда присутствует только условие, точки с запятой ; можно опустить.

Использование цикла For

Теперь, когда мы освоили синтаксис, давайте перепишем нашу первую программу string.go, используя цикл.

package main

import "fmt"

func main() {
    s := "labex"
    for i := 0; i < len(s); i++ {
        fmt.Printf("%d %c\n", int(s[i]), s[i])
    }
}

Запустите программу:

go run string.go

Вывод:

108 l
97 a
98 b
101 e
120 x

Упражнение

Давайте закрепим знания на практике.

Создайте файл for2.go. Ваша задача — вывести каждый символ строки "labex" в обратном порядке.

Ожидаемый результат:

x
e
b
a
l

Требования:

  • Файл for2.go должен находиться в директории ~/project.
  • Для решения задачи используйте цикл for.

Подсказка: Индексация начинается с 0, а индекс последнего элемента равен длине строки минус один.

Ключевое слово "break"

Ранее мы упоминали, что все три части цикла for необязательны. Что произойдет, если не указать ни одну из них? Давайте проверим.

Запишите следующий код в файл for.go:

package main

import "fmt"

func main() {
    for {
        fmt.Printf("1")
    }
}

Запустите программу:

go run for.go

Вы увидите, что если условие не задано, оно считается истинным (true) по умолчанию, и цикл становится бесконечным.

Совет: Используйте комбинацию клавиш Ctrl+C, чтобы принудительно остановить выполнение программы.

Если нам нужно выйти из цикла при определенном условии, не полагаясь на заголовок цикла, мы используем ключевое слово break. Оно немедленно прерывает выполнение текущего цикла.

Обновите файл for.go, чтобы вывести символ "1" ровно 23 раза с помощью break:

package main

import "fmt"

func main() {
    i := 0
    for {
        // Увеличиваем i на 1 в каждой итерации
        i++
        fmt.Printf("1")
        // Выходим из цикла, когда i достигнет 23
        if i == 23 {
            break
        }
    }
}

Ключевое слово break можно использовать как в бесконечных циклах, так и в обычных циклах с условием. Как только срабатывает break, выполнение цикла прекращается, и управление передается следующей за циклом инструкции.

Ключевое слово "continue"

Помимо break, который полностью останавливает цикл, существует ключевое слово continue. Оно позволяет пропустить оставшуюся часть кода в текущей итерации и немедленно перейти к следующей.

Использование continue похоже на break, но результат принципиально иной.

Давайте обновим файл for.go, чтобы вывести числа от 0 до 9, пропустив при этом 2 и 8:

package main

import "fmt"

func main() {
    for i := 0; i < 10; i++ {
        if i == 2 || i == 8 {
            continue
        }
        fmt.Println(i)
    }
}

Запустите программу:

go run for.go

Результат:

0
1
3
4
5
6
7
9

В этой программе мы добавили проверку внутри цикла. Если значение i равно 2 или 8, выполняется команда continue, которая заставляет программу проигнорировать вызов fmt.Println(i) и сразу перейти к следующему шагу цикла.

Резюме

В ходе этой лабораторной работы мы изучили цикл for. Подведем итоги:

  • Все три параметра цикла for (инициализация, условие, пост-условие) являются необязательными.
  • Ключевое слово break используется для немедленного выхода из цикла.
  • Ключевое слово continue позволяет пропустить текущую итерацию и перейти к следующей.
✨ Проверить решение и практиковаться