Объявление цикла ForClause и циклов с условием
Чтобы учесть самые разные случаи использования, существует три разных способа создания циклов for
в Go, каждый из которых имеет свои возможности. Вы можете создать цикл for
с условием, ForClause и RangeClause. В этом разделе мы расскажем, как объявлять и использовать ForClause и цикл с условием.
Давайте посмотрим, как мы можем использовать цикл for
с ForClause.
Цикл ForClause определяется как цикл с инициирующим оператором, за которым следует условие и пост-оператор. Они имеют следующий синтаксис:
for [ Initial Statement ] ; [ Condition ] ; [ Post Statement ] { [Action] }
Чтобы объяснить, что делают компоненты выше, давайте рассмотрим цикл for
, который выполняет увеличение в указанном диапазоне значений с помощью синтаксиса ForClause:
for i := 0; i < 5; i++ { fmt.Println(i) }
Copy
Давайте разобьем этот цикл на части и рассмотрим каждую часть.
Первая часть цикла — i := 0
. Это инициирующий оператор:
for i := 0; i < 5; i++ { fmt.Println(i) }
Он указывает, что мы объявляем переменную с именем i
и задаем первоначальное значение 0
.
Далее идет условие:
for i := 0; i < 5; i++ { fmt.Println(i) }
В этом условии мы указываем, что пока i
меньше 5
, цикл будет продолжать работу.
А в конце мы получаем пост-оператор:
for i := 0; i < 5; i++ { fmt.Println(i) }
В этой части мы инкрементируем значение переменной i
на 1 каждый раз после каждой итерации с помощью оператора инкремента i++
.
При запуске этой программы вывод выглядит следующим образом:
Output 0 1 2 3 4
Цикл отработал 5 раз. Первоначально он задает для i
значение 0
, а затем проверяет, является ли значение i
меньше 5
. Так как значение i
меньше 5
, цикл выполняется и функция fmt.Println(i)
исполняется. После завершения цикла вызывается оператор i++
, а значение i
увеличивается на 1.
Примечание. Необходимо помнить, что в программировании мы обычно начинаем индексы с 0, поэтому хотя было выведено 5 чисел, они варьируются в диапазоне от 0 до 4.
Мы не обязательно должны начинать с 0 или заканчивать заданным значением. Мы можем присвоить любое значение для нашего инициирующего оператора и останавливать работу цикла на любом значении пост-оператора. Это позволяет нам создавать желаемый диапазон для работы цикла:
for i := 20; i < 25; i++ { fmt.Println(i) }
Copy
Здесь итерация выполняется с 20 (включая) до 25 (не включая), поэтому вывод выглядит следующим образом:
Output 20 21 22 23 24
Также мы можем использовать наш пост-оператор для инкрементирования на различных значениях. Это аналогично шагу
в других языках:
Сначала давайте воспользуемся пост-оператором с положительным значением:
for i := 0; i < 15; i += 3 { fmt.Println(i) }
В данном случае цикл for
задан таким образом, чтобы выводить числа с 0 до 15, но с увеличением на 3, так что на экран будет выводиться только каждое 3 число:
Output 0 3 6 9 12
Также мы можем использовать отрицательное значение для аргумента пост-оператора, чтобы выполнять итерацию в обратном направлении, но при этом нам нужно будет изменить инициирующий оператор и аргументы условий:
for i := 100; i > 0; i -= 10 { fmt.Println(i) }
Copy
Здесь мы зададим для i
начальное значение 100
, воспользуемся условием i < 0
для остановки при 0
, а в пост-операторе будем уменьшать значение на 10 с помощью оператора -=
. Цикл начинает работу при 100
и заканчивается при 0
, а значение уменьшается на 10 при каждой итерации. Вы можете увидеть, как это происходит, в выводе:
Output 100 90 80 70 60 50 40 30 20 10
Также вы можете исключить инициирующий оператор и пост-оператор из синтаксиса for
и использовать только условие. Это так называемый цикл с условием:
i := 0 for i < 5 { fmt.Println(i) i++ }
На этот раз мы объявили переменную i
отдельно от цикла for
в предшествующей строке кода. Цикл имеет только одно условие, которое проверяет, остается ли i
менее 5
. Если условие возвращает true
, цикл будет продолжаться.
Иногда вы можете не знать количество итераций, которое вам потребуется для выполнения определенной задачи. В этом случае вы можете пропустить все операторы и использовать ключевое слово break
для прекращения цикла:
for { if someCondition { break } // do action here }
Подобный пример можно использовать, если мы будем выполнять чтение из структуры с неопределенным размером, например, из буффера, и мы не знаем, когда чтение будет завершено:
buffer.go
package main import ( "bytes" "fmt" "io" ) func main() { buf := bytes.NewBufferString("one\ntwo\nthree\nfour\n") for { line, err := buf.ReadString('\n') if err != nil { if err == io.EOF { fmt.Print(line) break } fmt.Println(err) break } fmt.Print(line) } }
Copy
В предыдущем коде buf :=bytes.NewBufferString("one\ntwo\nthree\nfour\n")
объявляет буфер с некоторыми данными. Поскольку мы не знаем, когда буфер завершит чтение, мы создадим цикл for
без условия. Внутри цикла for
мы используем строку line, err := buf.ReadString('\n')
для считывания строки из буфера и проверки на наличие ошибок при чтении из буфера. Если произошла ошибка, мы устраняем ее и используем ключевое слово break
для выхода из цикла. С этими точками break
вам не нужно добавлять условие, чтобы остановить цикл.