Start learning free

LESSON 192 OF 338 · NESTED LOOPS & BRUTE FORCE

Nested Loops in Go: Rows, Columns and break

Lesson Read the full explanation

A nested loop has one loop inside of another. These are typically used for working with two dimensions such as printing stars in rows and columns as shown below. When a loop is nested inside another loop, the inner loop runs many times inside the outer loop. In each iteration of the outer loop, the inner loop will be re-started. The inner loop must finish all of its iterations before the outer loop can continue to its next iteration.

Example:

for row := 0; row < 3; row++ {
	for col := 0; col < 5; col++ {
		fmt.Print("*")
	}
	fmt.Println()
}

// This code prints a rectangle with 3 rows and 5 columns, filled with '*'

Iterating through multidimensional arrays

Nested loops are also helpful when we want to iterate through a multi dimensional array, for example:

arr := [][]int{
	{1, 2},
	{3, 4},
	{5, 6},
}

for i := 0; i < 3; i++ {
	for j := 0; j < 2; j++ {
		fmt.Println(arr[i][j])
	}
}

// This outputs each sub-element in arr one at a time

Breaking nested loops

In a nested loop, a break statement only stops the loop it is placed in. Therefore, if a break is placed in the inner loop, the outer loop still continues. For example:

arr := [][]int{
	{1, 2},
	{3, 4},
	{5, 6},
}

for i := 0; i < 3; i++ {
	for j := 0; j < 2; j++ {
		if arr[i][j] == 3 {
			break
		}
		fmt.Println(arr[i][j])
	}
}

// prints the numbers 1, 2, 5 and 6 on different lines

When i is 1 and j is 0, we execute the break. This means we stop the inner loop and go back to the outer loop to continue from the next iteration, which is i = 2. And as you can see, we print all the elements of row 2.

However, if the break is placed in the outer loop, all of the looping stops. For example:

arr := [][]int{
	{1, 2},
	{3, 4},
	{5, 6},
}

for i := 0; i < 3; i++ {
	if arr[i][0] == 3 {
		break
	}
	for j := 0; j < 2; j++ {
		fmt.Println(arr[i][j])
	}
}

// prints the numbers 1 and 2 on different lines

Assignment
Follow the Coding Tutorial and let's write some nested loops.


Hint
Look at the examples above if you get stuck.


STEP 1 OF 4
    Ctrl + Enter to check

    GO · NESTED LOOPS & BRUTE FORCE

    Nested Loops in Go, explained

    What a nested loop is

    A nested loop is a loop inside another loop. For every pass of the outer loop, the inner loop starts again from its initial value and runs to completion. If the outer loop runs 5 times and the inner loop 10 times, the inner body runs 5 × 10 = 50 times.

    Go has a single loop keyword, for, so every nested loop is made of for statements. The three-part form is init; condition; post, with no parentheses and with braces always required.

    Printing a rectangle

    The classic use is a grid. The outer loop counts rows and the inner loop counts columns:

    for row := 0; row < 3; row++ {
        for col := 0; col < 5; col++ {
            fmt.Print("*")
        }
        fmt.Println()
    }
    *****
    *****
    *****

    fmt.Print writes without a newline, so the five stars of a row stay together. fmt.Println() with no arguments ends the line. It sits after the inner loop's closing brace but inside the outer loop: placed inside the inner loop, it would put every star on its own line.

    Walking a slice of slices

    Nested loops also visit every element of a two-dimensional slice. Here arr[i][j] is element j of row i:

    arr := [][]int{
        {1, 2},
        {3, 4},
        {5, 6},
    }
    
    for i := 0; i < len(arr); i++ {
        for j := 0; j < len(arr[i]); j++ {
            fmt.Println(arr[i][j])
        }
    }

    This prints 1 to 6, one per line. The trailing comma after {5, 6} is required because the closing brace is on its own line. Using len(arr[i]) for the inner bound keeps the loop correct when rows have different lengths. The range form is shorter when the indices are not needed:

    for _, row := range arr {
        for _, v := range row {
            fmt.Print(v, " ")
        }
        fmt.Println()
    }
    1 2 
    3 4 
    5 6 

    break in nested loops

    A break leaves only the loop it is written in. In the inner loop it ends that row's scan, and the outer loop carries on with the next row:

    for i := 0; i < 3; i++ {
        for j := 0; j < 2; j++ {
            if arr[i][j] == 3 {
                break
            }
            fmt.Println(arr[i][j])
        }
    }
    1
    2
    5
    6

    At i = 1, j = 0 the value is 3, so the inner loop stops. The outer loop moves to i = 2 and prints all of row 2. The numbers 3 and 4 never appear.

    A break in the outer loop, before the inner loop starts, stops everything:

    for i := 0; i < 3; i++ {
        if arr[i][0] == 3 {
            break
        }
        for j := 0; j < 2; j++ {
            fmt.Println(arr[i][j])
        }
    }
    1
    2

    Leaving both loops with a label

    To stop both loops from inside the inner one, Go lets you put a label before the outer for and name it in break:

    outer:
        for i := 0; i < 3; i++ {
            for j := 0; j < 2; j++ {
                if arr[i][j] == 3 {
                    break outer
                }
                fmt.Println(arr[i][j])
            }
        }

    This prints only 1 and 2. A continue can use a label the same way, to jump to the next pass of the outer loop.

    Common mistakes

    • Reusing the loop variable. Give each loop its own name, such as row and col. Reusing the same name shadows the outer variable and breaks the logic.
    • Putting the newline in the wrong place. fmt.Println() belongs after the inner loop.
    • Off-by-one bounds. i < len(arr) is correct; i <= len(arr) panics with an index out of range error on the last pass.
    • Expecting a plain break to leave both loops. It does not; use a label or a flag.

    The exercise, step by step

    The task is a rectangle of stars with 5 rows and 10 columns.

    1. Write the outer loop with row starting at 0 and running while row < 5: one pass per row.
    2. Write the inner loop inside it with col from 0 while col < 10: one pass per column. Its body runs 50 times in total.
    3. Print one star with fmt.Print("*") inside the inner loop.
    4. End the row with fmt.Println() after the inner loop, still inside the outer one.
    for row := 0; row < 5; row++ {
        for col := 0; col < 10; col++ {
            fmt.Print("*")
        }
        fmt.Println()
    }

    The output is five lines of ten stars each.

    Key takeaways

    • The inner loop restarts and finishes completely on every pass of the outer loop.
    • The body of two nested loops over n and m items runs n * m times.
    • break affects only the innermost loop; a labeled break leaves an outer one.
    • Rows are the outer loop and columns the inner loop when printing or walking a grid.
    Keep going with GoAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free