19. Nested loops
A loop repeats a block. What if that block holds another loop? That is a nested loop: the inner one runs fully on every round of the outer one. Nested loops build grids, tables, and anything with rows and columns.
A loop inside a loop
Put one for inside another. The inner loop finishes
before the outer one moves:
for outer := 1; outer <= 3; outer++ {
for inner := 1; inner <= 2; inner++ {
fmt.Println(outer, inner)
}
}Output:
1 1
1 2
2 1
2 2
3 1
3 2
Follow the order. While outer is 1, the
inner loop runs (1, 2). Then
outer becomes 2 and it runs again. That is
3 × 2 = 6 runs.
Give the two loop variables different names.
row/col or i/j are
common pairs. Using i for both compiles, but the inner
i is a new variable that hides the outer one, so inside the
inner loop you cannot read the outer count:
for i := 1; i <= 2; i++ {
for i := 1; i <= 2; i++ {
fmt.Println("inner", i)
}
fmt.Println("outer", i)
}Output:
inner 1
inner 2
outer 1
inner 1
inner 2
outer 2
Building a row at a time
One value per line rarely suits a grid. The usual trick: the
outer loop handles rows; the inner
loop builds one string, printed when the row is done. +=
adds to the string, and strconv.Itoa from Chapter 14 turns
each number into text:
for row := 1; row <= 3; row++ {
line := ""
for col := 1; col <= 3; col++ {
line += strconv.Itoa(row*col) + "\t"
}
fmt.Println(line)
}Output (a 3×3 multiplication grid):
1 2 3
2 4 6
3 6 9
Notice line := "" sits inside the outer loop
but outside the inner one. It resets each row, fills up in the
inner loop, then prints. The "\t" from Chapter 12 puts a
tab after each number, which lines up the columns.
Open exercises/19/01-grid.go. It prints a 3×3 grid.
Change only the two end values to make it 5×5.
A triangle with a changing inner loop
The inner loop's condition can depend on the outer variable. Run it
from 1 to row and you get a triangle:
for row := 1; row <= 4; row++ {
line := ""
for star := 1; star <= row; star++ {
line += "*"
}
fmt.Println(line)
}Output:
*
**
***
****
Row 1 runs the inner loop once; row 4 runs it four times. The shape comes from the maths.
strings.Repeat("*", row) from Chapter 14 would build
each row in one call. Writing the loop yourself is the practice here,
and many grids have rows that strings.Repeat cannot build,
like the multiplication grid above.
How many times does the body run?
Multiply the counts. An outer loop of 10 around an inner loop of 10
runs the body 10 × 10 = 100 times. It grows fast: three
loops of 100 each is a million runs. A computer handles a million simple
runs quickly, but the count is worth working out before you add another
level.
Homework
Homework starters are in exercises/19/homework/. Each
one runs as it is and prints a placeholder line.
Problem 1 — Rectangle of hashes
Open exercises/19/homework/01-rectangle.go. With nested
loops, print a rectangle of # 5 wide and 3 tall:
#####
#####
#####
Problem 2 — Coordinate pairs
Open exercises/19/homework/02-coords.go. Print every
(x, y) pair for x and y from 1 to
3, one per line: (1, 1), (1, 2), and so on.
Nine lines.
Problem 3 — Times table
Open exercises/19/homework/03-times-table.go. Print the
full multiplication grid from 1×1 to 5×5: five
rows of five numbers each, with a tab after each number.
Challenge — Right triangle
Open exercises/19/homework/04-triangle.go. Print a
right-angled triangle of * 6 rows tall, where row
n has n stars. For a stretch, flip it upside
down (6 stars on the first row, 1 on the last).
Stuck or finished? Open the homework solutions page.