Цикл for: повторить тело несколько раз
Этикеток на партию бывает и три, и триста, а сколько — программа узнаёт только при запуске. Триста раз писать Println нельзя: нужен цикл — конструкция, которая повторяет кусок кода столько раз, сколько надо. В Go для этого одно слово: for.
Три части заголовка
Ситуация. Для партии из трёх коробок нужно напечатать три этикетки.
package main
import "fmt"
func main() {
for i := 0; i < 3; i++ {
fmt.Println("Этикетка номер", i)
}
fmt.Println("Этикетки готовы")
}Что увидите.
stagiaire@lab:~/gocourse/day08/scratch$ go run .
Этикетка номер 0
Этикетка номер 1
Этикетка номер 2
Этикетки готовыКак это читать. Строка с for — заголовок: три части через точку с запятой. В фигурных скобках — тело, то, что повторяется.
| Кусок | Когда выполняется | Что делает |
|---|---|---|
i := 0 |
один раз, до всего | создаёт переменную цикла — счётчик |
i < 3 |
перед каждым проходом | истинно — тело, ложно — выход из цикла |
i++ |
после каждого прохода | плюс единица к счётчику |
{ … } |
пока условие истинно | тело цикла |
Порядок такой: i := 0; проверка истинна — тело, потом i++ и проверка снова; так трижды, при i = 0, 1, 2; после третьего i++ в i уже 3, проверка 3 < 3 ложна, и программа идёт к строке после }. Условие проверено четыре раза, тело выполнилось три: последняя проверка всегда ложная, иначе цикл бы не кончился. Один проход тела — итерация.
Круглых скобок вокруг заголовка нет, фигурные обязательны, { — в конце строки с for. Имя i — традиция, годится любое.
Попробуйте сейчас: этикетки в цикле.
Цель: своя программа с циклом, у которой число проходов задаёт переменная.
1. Наберите в
scratch/main.goпрограмму из раздела «Три части заголовка»:✎ Наберите в файлscratch/main.gopackage main import "fmt" func main() { for i := 0; i < 3; i++ { fmt.Println("Этикетка номер", i) } fmt.Println("Этикетки готовы") }Запустите:
▶ Выполнитеcd ~/gocourse/day08/scratch go run .2. Поменяйте
3на5: этикеток пять, аPrintlnодна.3. Объявите до цикла
n := 4, условие —i < n: число проходов задаёт переменная, а её можно будет прочитать из ввода. Запустите.Готово, когда: печатается
Этикетка номер 0…3иЭтикетки готовы, а в заголовке стоитi < n.
Переменная цикла живёт внутри
Ситуация. После этикеток нужно напечатать, сколько коробок в партии. Кажется, это последнее значение i.
Дальше показаны только строки тела main: вставляйте их между { и } в scratch/main.go. С одним import "fmt" первая строка тела — шестая.
for i := 0; i < 3; i++ {
fmt.Println("Коробка", i)
}
fmt.Println("Всего коробок:", i)stagiaire@lab:~/gocourse/day08/scratch$ go run .
# day08/scratch
./main.go:9:44: undefined: ii объявлена в заголовке и живёт до закрывающей } цикла — как переменная внутри if в день 06: на строке 9 её уже нет (колонка 44 — в байтах). Нужно значение после цикла — переменную объявляют до него, а в теле меняют:
count := 0
for i := 0; i < 3; i++ {
fmt.Println("Коробка", i)
count++
}
fmt.Println("Всего коробок:", count)stagiaire@lab:~/gocourse/day08/scratch$ go run .
Коробка 0
Коробка 1
Коробка 2
Всего коробок: 3count — счётчик: до цикла ноль, в каждом проходе плюс один (о таких переменных — вся страница 6). Объявленная в теле переменная создаётся заново на каждом проходе, и правило «объявил — используй» для неё то же:
for day := 1; day <= 3; day++ {
sold := day * 10
}
fmt.Println("готово")stagiaire@lab:~/gocourse/day08/scratch$ go run .
# day08/scratch
./main.go:7:3: declared and not used: soldПопробуйте сейчас: переменная цикла после цикла.
Цель: увидеть
undefined: i, починить счётчиком, записать в словарик.1. Наберите в
scratch/main.goвариант сiпосле цикла:✎ Наберите в файлscratch/main.gopackage main import "fmt" func main() { for i := 0; i < 3; i++ { fmt.Println("Коробка", i) } fmt.Println("Всего коробок:", i) }▶ Выполнитеcd ~/gocourse/day08/scratch go run .Найдите в сообщении строку и имя.
2. Почините через счётчик
countи запустите снова.3. Запишите
undefined: iв~/errors.md: текст ошибки, тире, что это значило.Готово, когда: печатается
Всего коробок: 3, а в~/errors.mdесть строка проundefined: i— она идёт в пунктerrors.
Что может пойти не так
Номер строки и колонки в сообщениях свой, текст — тот же.
| Что видите | Что это значит | Что делать |
|---|---|---|
undefined: i |
переменную цикла читают после цикла | объявить до цикла, менять в теле |
declared and not used: sold |
переменную в теле объявили и не читают | использовать или удалить |
syntax error со словами after for clause или expected ) |
заголовок не по-гошному: круглые скобки, запятые вместо ;, { на своей строке |
таблица чужого синтаксиса в course extra 08 |
после Ctrl+S скобки в for (n > 0) { исчезли |
вокруг одного условия скобки допустимы, gofmt убирает их как лишние |
так и оставить |
Попробуйте сейчас: что напечатает программа.
Цель: предсказать вывод цикла, который меняет свою же границу.
1. Сначала не запуская: выпишите на бумаге
iиnпосле каждой проверки условия.Код для чтения · разбираем, набирать не нужноn := 5 for i := 0; i < n; i++ { n-- } fmt.Println(n)Условие проверяется перед каждым проходом, и
nв нём — то, что лежит там сейчас.2. Сдать число (вместо
ЧИСЛО— своё предсказание):▶ Выполните · выделенное замените своимcourse answer day08.q1 ЧИСЛО3. Потом проверьте запуском — программа целиком:
✎ Наберите в файлscratch/main.gopackage main import "fmt" func main() { n := 5 for i := 0; i < n; i++ { n-- } fmt.Println(n) }▶ Выполнитеcd ~/gocourse/day08/scratch go run .Готово, когда: пункт
q1вcourse check 08зелёный.
Дальше: сколько раз выполнится тело и ошибка на единицу — course next