Computers are good at doing the same thing many times without getting bored or making slips. A loop is a statement that runs a block of code repeatedly. Go has exactly one loop statement, for, and this lesson shows the two ways you will write it.
for repeats a fixed number of times
package main
import "fmt"
func main() {
for i := 1; i <= 3; i++ {
fmt.Println("Hello")
}
fmt.Println("Done")
}This prints Hello three times and then Done once.
The line that starts with for has three parts, separated by semicolons:
i := 1is the start. It runs once, before anything else, and creates a variable to count with. This variable is called the loop variable.i <= 3is the condition. Go checks it before every run of the block. While it is true, the block runs; as soon as it is false, the loop is over.i++is the step. It runs after every run of the block. Here it adds one toi.
So the order is: start, check, block, step, check, block, step, check, and so on until a check fails. Each run of the block is called an iteration. The program then carries on with the statement after the closing curly bracket.
As with if, there are no round brackets around the three parts, and the opening curly bracket stays on the for line.
Using the loop variable
The loop variable is an ordinary int, and the block can use it. It has a different value on each iteration.
package main
import "fmt"
func main() {
for i := 1; i <= 4; i++ {
fmt.Println(i, "times 7 is", i*7)
}
}This prints:
1 times 7 is 7
2 times 7 is 14
3 times 7 is 21
4 times 7 is 28Programmers often count from zero instead: for i := 0; i < 4; i++ also runs four times, with i taking the values 0, 1, 2 and 3. Notice that it uses <, not <=. Both styles are common. What matters is that the start and the condition agree with each other.
The step does not have to be i++. i += 2 counts in twos, and i-- counts down.
A running total
A very common pattern: create a variable before the loop, change it inside the loop, and use it after the loop.
package main
import "fmt"
func main() {
total := 0
for number := 1; number <= 3; number++ {
total += number
}
fmt.Println(total)
}This prints 6, which is 1 + 2 + 3. The variable total is called a running total because it holds the sum so far at every moment.
number takes the values 1, 2 and 3 in turn. Each iteration adds the current number to total. When number reaches 4 the condition is false and the loop ends.The line total := 0 must come before the loop. If it were inside the block, it would create a fresh total on every iteration and the sum so far would be lost each time.
for with only a condition
Sometimes you do not know in advance how many iterations are needed. You only know when to stop. For that, write for with the condition alone:
package main
import "fmt"
func main() {
countdown := 3
for countdown > 0 {
fmt.Println(countdown)
countdown--
}
fmt.Println("Lift off!")
}This prints 3, 2, 1 and then Lift off!.
Go checks the condition. If it is true, the block runs and Go goes back and checks again. If it is false, the loop ends. Many other languages have a separate word, while, for this kind of loop. In Go it is still for.
The line countdown-- is what brings the loop to an end. Without it, countdown would stay 3, the condition would stay true and the program would print 3 for ever. A loop that never ends is called an infinite loop. On this site a program stuck in one is stopped after a few seconds.
Loops that read input
A loop can prompt and read on every iteration. This program adds up whatever the user types until they type 0:
package main
import (
"bufio"
"fmt"
"os"
"strconv"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
total := 0
number := 1
for number != 0 {
fmt.Print("Number (0 to stop): ")
scanner.Scan()
typed, err := strconv.Atoi(scanner.Text())
if err != nil {
fmt.Println("Please type a whole number.")
return
}
number = typed
total += number
}
fmt.Println("Total:", total)
}A session:
Number (0 to stop): 5
Number (0 to stop): 20
Number (0 to stop): 0
Total: 25number starts at 1 only so that the condition is true the first time. Inside the block, the converted value is first received in a new variable, typed, and then assigned to number with =. Writing number, err := ... inside the block would create a second, separate number that exists only inside the curly brackets, and the one in the condition would never change.
Try it in the playground with a few numbers and a final 0 in the Standard input box.
Off-by-one mistakes
The most common loop mistake is running one time too many or one time too few. It is called an off-by-one mistake. Compare:
for i := 1; i <= 5; i++runs 5 times: 1, 2, 3, 4, 5.for i := 1; i < 5; i++runs 4 times: 1, 2, 3, 4.for i := 0; i < 5; i++runs 5 times: 0, 1, 2, 3, 4.for i := 0; i <= 5; i++runs 6 times: 0, 1, 2, 3, 4, 5.
When a loop's output is nearly right, check the first value and the last value by hand. Ask: what is the loop variable on the first iteration, and what is the last value for which the condition is still true?
Two errors you will meet
Using the loop variable after the loop. A variable created in the for line exists only inside that loop.
package main
import "fmt"
func main() {
for i := 1; i <= 3; i++ {
fmt.Println(i)
}
fmt.Println("Finished at", i)
}# command-line-arguments
./main.go:9:32: undefined: iOn line 9 the loop is over and i no longer exists. The same is true of any variable created with := inside a block: it disappears at the closing curly bracket. If you need a value after the loop, create its variable before the loop, as total was.
Creating a new variable inside the block by accident.
package main
import "fmt"
func main() {
total := 0
for i := 1; i <= 3; i++ {
total := total + i
}
fmt.Println(total)
}# command-line-arguments
./main.go:8:9: declared and not used: totalLine 8 uses :=, so it creates a second total inside the block instead of changing the one from line 6. Nothing ever reads the new one, and the compiler says so. Write total = total + i or total += i.
What you can do now
You can repeat a block a fixed number of times with a counting for, repeat until a condition changes with a condition-only for, keep a running total, read input inside a loop, and check a loop's first and last iteration for off-by-one mistakes. In the exercises you will trace loops, repair two that miscount and write a program that adds up numbers.
Next: write functions and finish a complete program, the last lesson of this unit.