18. Loops
The other way out of repeating yourself is the loop:
a block of code that runs over and over. Chapters 03 and 04 showed that
Go has one loop keyword, for, and no other.
for comes in several forms, plus break for
stopping early and continue for skipping a round. All are
covered here.
for
with a condition: repeat as long as it is true
The most general form has just a condition. Go checks it, runs the block if it is true, then checks again, repeating until it is false.
count := 10
for count > 0 {
fmt.Println(count)
count = count - 1
}
fmt.Println("Blast off!")Run order:
- Check
count > 0. It is10, so true. - Print
10, setcountto9. - Back to step 1.
countis9, still true. Print, subtract one. - Repeat until
countis0. The condition fails, the loop exits, andfmt.Println("Blast off!")runs once.
The rules from if apply: no parentheses, and the
{ stays on the same line. This is
exercises/18/02-countdown.go.
Inside the body, change a value the condition depends on, or the loop never ends. An infinite loop locks the terminal. Stop it with Ctrl + C.
Shorter ways to change a variable
Loops change variables all the time, so Go has short forms.
i++ adds 1 to i, which you have seen since
Chapter 04. i-- subtracts 1. +=,
-=, and *= apply an operation to the variable
itself, so total += 5 means total = total + 5.
+= joins strings too:
score := 10
score++
fmt.Println(score) // 11
score--
score--
fmt.Println(score) // 9
score += 5
fmt.Println(score) // 14
score -= 4
fmt.Println(score) // 10
score *= 3
fmt.Println(score) // 30
line := "ab"
line += "c"
fmt.Println(line) // abcscore++ is a statement on its own line. It does not give
a value, so you cannot write it inside fmt.Println.
The
three-part for: repeat a known number of times
This is the right form when you know how many times to repeat. You met it in Chapter 04:
for i := 1; i <= 5; i++ {
fmt.Println(i)
}Output:
1
2
3
4
5
The three parts are separated by semicolons:
i := 1runs once, before the first round.i <= 5is the condition, checked before each round.i++runs after each round.
Watch the end value. i <= 5 includes 5, and
i < 5 stops at 4. Getting this wrong by one is the most
common bug in loops, so read the condition carefully. To loop from 1 to
10, write i <= 10.
A variable declared in the first part exists only inside the loop. Using it afterwards stops with:
for i := 1; i <= 3; i++ {
fmt.Println(i)
}
fmt.Println(i)undefined: i
If you need the counter after the loop, declare it before the loop, as the condition form does.
A step
The third part sets how the counter changes each round. Change it to skip or to count backwards:
for i := 0; i <= 100; i += 10 {
fmt.Print(i, " ")
}
fmt.Println()
for i := 10; i > 0; i-- {
fmt.Print(i, " ")
}
fmt.Println()Output:
0 10 20 30 40 50 60 70 80 90 100
10 9 8 7 6 5 4 3 2 1
The direction has to match the condition.
for i := 10; i > 0; i++ starts above zero and keeps
going up, and i += 0 never changes i at all.
Go accepts both, and the loop does not end when you meant it to.
fmt.Print(i, " ") prints a value and a space, with no
new line. The plain fmt.Println() at the end moves to a new
line. These examples are in exercises/18/04-step.go.
Open exercises/18/01-for-table.go. It prints the
multiplication table of 7, from 7 * 1 to
7 * 10. Change it to print the table of any other
number.
The bare for with
break
Any loop can be cut short with break, which jumps
straight to whatever comes after the loop. A for with
nothing after it has no built-in exit, and the only way out is
break:
n := 1
for {
if n*n > 100 {
break
}
n++
}
fmt.Println("First number whose square is over 100 is", n)Output:
First number whose square is over 100 is 11
Use the bare for when the exit test does not fit in a
single condition at the top. This is
exercises/18/05-break.go.
Inside a switch, break leaves the
switch, not the loop around it:
for i := 1; i <= 3; i++ {
switch i {
case 2:
fmt.Println("break here")
break
}
fmt.Println("after the switch, i is", i)
}Output:
after the switch, i is 1
break here
after the switch, i is 2
after the switch, i is 3
The loop carried on. When a loop has to end from inside a decision,
use an if chain for that decision.
Running at least once
Sometimes the body must run at least once before the check. Use a
bare for with break at the end:
count := 1
for {
fmt.Println(count)
count++
if count > 5 {
break
}
}Output:
1
2
3
4
5
The break at the bottom exits as soon as the condition
is met. This is the shape for asking the user something: you have to ask
once before you can check the answer. This is
exercises/18/03-at-least-once.go.
continue: skip to
the next round
Where break exits the loop entirely,
continue skips the rest of the current round and goes
straight to the next one:
for i := 1; i <= 10; i++ {
if i%2 == 0 {
continue // skip even numbers
}
fmt.Println(i)
}Output:
1
3
5
7
9
In a three-part for, the i++ still runs
after continue. In a condition form, make sure the variable
has already changed before continue, or the loop never
ends. The same result can always be written without
continue, but it can make the intent clearer. This is
exercises/18/06-continue.go.
range over a number
When you only want "do this N times", range is shorter.
It counts from 0 up to, but not including, the number:
for i := range 3 {
fmt.Println("Round", i)
}
for range 2 {
fmt.Println("Push-up")
}Output:
Round 0
Round 1
Round 2
Push-up
Push-up
The second form leaves out the variable, for when you do not need the
count. This form needs Go 1.22 or newer, which the setup in Chapter 06
gives you. This is exercises/18/07-range-number.go. Chapter
22 uses range to walk through a slice. The rest of this
part uses the three-part form, because it can start anywhere and take
any step.
Homework
Homework starters are in exercises/18/homework/. Each
one runs as it is and prints a placeholder line.
Problem 1 — Count to 20
Open exercises/18/homework/01-count-to-20.go. Use a
for with only a condition to print 1 to 20, each on its own
line.
Problem 2 — Multiplication table of 7
Open exercises/18/homework/02-mult-table-7.go. Use a
three-part for to print the multiplication table of 7, from
7 * 1 to 7 * 12, in this shape:
7 * 1 = 7
7 * 2 = 14
...
7 * 12 = 84
Problem 3 — Stop at the threshold
Open exercises/18/homework/03-stop-at-threshold.go. Loop
from 1, adding each number to a running total. Stop once the total
exceeds 100, then print the total and the counter value at that
moment.
Challenge — Sum 1..N
Open exercises/18/homework/04-sum-1-to-n.go. Prompt for
a positive whole number n. Compute
1 + 2 + 3 + ... + n with a for loop and a
running total. Print:
Sum from 1 to N is S
Then print the formula n * (n + 1) / 2 on the next line,
which gives the same answer without a loop. The two should agree.
Stuck or finished? Open the homework solutions page.