Go for loops & Iteration Control Tutorial

In this Go tutorial we learn how to repeat sections of our code with the for loop.

We learn how to use the condition-controlled variation (like a while loop) and the counter-controlled variation (standard for loop). We also learn how to nest a for loop inside another for loop.

Lastly we learn how to break out of a loop and how to skip an iteration of the loop with loop control statements.

What is iteration control and looping

In programming, we often need to execute sections of our code more than once.

Instead of rewriting these sections, we place them in a loop and allow Go to automatically execute them as many times as we need to.

There are two variants of the for loop in Go. Counter-controlled iteration and condition-controlled iteration.

If you’re familiar with other programming languages, like C#, the Go for loop can be used as both a for and a while loop.

The condition-controlled for loop

The condition-controlled version of the for loop is similar to an if statement and consists of the following.

  • A condition
  • A code block that contains our execution code that we want to repeat

The compiler will evaluate the condition and if it proves true, will execute the code in the block. Once the code in the block has finished, the compiler will start again at the top of the loop and evaluate the condition again.

Syntax:
for condition {
    // code to repeat
    // until condition
    // is false
}

Note that, unlike an if statement, the condition is not wrapped in parentheses.

Example:
package main

import "fmt"

func main() {

    sum := 3

    for sum < 100 {

        fmt.Println(sum)
        sum += sum
    }
}

In the example above, we want to add the value of sum to itself while it’s value is below 100.

So, we create our variable sum with a starting number. Then, in the for loop’s condition, we specify that the loop may only run while sum is less than 100.

Finally, in the execution block, we print the value of sum to the console and then add sum to itself with the += operator.

Let’s look at the ouput the loop produces.

Output:
3
6
12
24
48
96

The first value printed is 3. It’s below 100 so the condition is true and the code block can execute.

The code block adds sum to itself after the print so the value of sum should now be 6.

When we look at the output, we see that 6 is printed in the second iteration.

This continues on until the compiler tries to add 96 and 96 together. The result would be greater than 100 so the compiler stops the loop.

The counter-controlled for loop

The counter-controlled variation of the for loop is used to execute code a set number of times.

This variation has a counter variable, a condition and a counter increment. Each of these are separated with a semicolon.

Syntax:
for counter; condition; increment counter {

    // code to execute
}

Typically, the condition is evaluated on the counter itself.

For example, if we want to loop through our code 5 times, we check if the counter variable value is below 5. Then, each time the loop runs, the counter is incremented by 1.

Example:
package main

import "fmt"

func main() {

    //  counter   condition  increment the counter
    for i := 0;   i <= 10;   i++  {

        fmt.Println("i:", i);
    }
}

The example above reads like this:

  • i is 0
  • If i is less than or equal to 10, add 1 to i and execute the code in the block.
  • Go back to the top of the loop.
  • i is 1
  • Repeat the process until i is 10, then exit the loop.

This variation of the for loop always has a counter that controls it, as opposed to a conditional for loop that doesn’t need a counter and can be controlled by something else, like a boolean.

The counter-controlled for loop is used when we know the number of times we want to loop, like the size of an array.

The range keyword

The range keyword is used in a for loop to iterate over array, slice, channel or map items.

If you’re familiar with a language like C#, the range keyword would be similar to a foreach loop.

Because range works with arrays, slices, channels and maps, we will cover it after learning about these topics.

If you’re already familiar with them, and want to learn about range right now, you can find the lesson here .

Nested loops

In Go we can nest one loop inside another. The loops will be executed hierarchically, which means the compiler will run an inner loop fully, before it moves on to the next iteration of the outer loop.

As an example, let’s consider that we want to create a chunk of blocks similar to that in Minecraft.

We would need to create blocks in each of the three axes, x, y and z. For that we would need to nest our loops.

Example:
package main

import "fmt"

func main() {

    // 16 x 16 square
    // 128 blocks high
    xSize := 16
    ySize := 16
    zSize := 128

    for x := 0; x <= xSize; x++  {

        for y := 0; y <= ySize; y++  {

            for z := 0; z <= zSize; z++  {

                // code to create blocks
                fmt.Printf("x: %d - y: %d - z: %d\n", x, y, z)
            }
        }
    }
}

In the example above, we print a message with the block number created on each axis.

It’s worth it to note that nesting more than 3 levels deep can become complicated very quickly. If you find yourself nesting more than three levels, consider another option.

Loop control statements: break

Go provides us with control statements to control the flow of our for loop. The first of these statements is the break statement.

The break control statement allows us to break out of a loop at any point by simply using the keyword break.

Example:
package main

import "fmt"

func main() {

    for x := 0; x <= 10; x++  {

        if (x == 6) {
            break
        }

        fmt.Println(x)
    }
}

In the example above, our loop will iterate until the counter gets to 10.

In the execution code however, we set up an if statement to break the loop when the counter reaches 6.

When we look at the output, we can see that the numbers only print up to 5, which means the loop was successfully stopped when it reached 6.

Output:
0
1
2
3
4
5

Loop control statements: continue

The continue control statement will skip anything after the keyword and move to the next iteration of the loop.

Example:
package main

import "fmt"

func main() {

    for x := 0; x <= 10; x++  {

        if (x == 6) {
            continue
        }

        fmt.Println(x)
    }
}

In the example above, our loop will once again iterate until the counter gets to 10.

But this time the if statement in the execution block tells the compiler to skip the print statement when it gets to 6, instead of completely breaking from the loop.

When we look at the output, we can see that 6 isn’t printed to the console, which means we successfully skipped that iteration.

Output:
0
1
2
3
4
5
7
8
9
10

Summary: Points to remember

  • Iteration control allows us to control the flow of our application by looping through sections of code.
  • Go only has one loop, the for loop, but it acts as both a condition-controlled loop and a counter-controlled loop.
  • The header section of a for loop is not wrapped in parentheses.
  • The range keyword is used to loop through lists like arrays, maps etc.
  • Loops can be nested inside other loops. It’s bad pratice to nest more than 3 levels deep.
  • The break control statement will completely break out of the loop and move on to the code below the loop.
  • The continue control statement will skip the current iteration of the loop. It will skip any code after the continue statement.