Start learning free

LESSON 109 OF 338 · FOR LOOPS - LOOPING OVER ARRAYS

For Loop Execution Flow in Go: What Is Inside the Loop

Lesson Read the full explanation

Go uses the brackets ({}) to indicate which lines of code are part of a for loop and which are not.

Take this code for example:

languages := []string{"Python", "Java", "JavaScript"}

for _, language := range languages {
  fmt.Println("I love " + language)
  fmt.Println("I want to get better at it")
}

Both fmt.Println statements are part of the loop since they are written inside the brackets.

This means that both messages will be printed for every language in the languages list. The output of that code would be:

I love Python
I want to get better at it
I love Java
I want to get better at it
I love JavaScript
I want to get better at it

As for this code:

languages := []string{"Python", "Java", "JavaScript"}

for _, language := range languages {
  fmt.Println("I love " + language)
}
fmt.Println("I want to get better at them")

The fmt.Println("I want to get better at them") is not part of the loop.

This means that only fmt.Println("I love " + language) will be executed for every language in the languages list.

Then, when the for loop is over, the fmt.Println("I want to get better at them") will be executed only once.

The output of this program would be:

I love Python
I love Java
I love JavaScript
I want to get better at them

Execution flow

Lastly, note that the execution of a program always begins on the first line. The code is then executed one line at a time from top to bottom. This is known as execution flow and is the order a program in Go executes code.

For example, this program:

fruits := []string{"banana", "apple", "kiwi"}

fmt.Println("I'm hungry!")

for _, fruit := range fruits {
  fmt.Println("I'm gonna eat:")
  fmt.Println(fruit)
}


fmt.Println("I love my life!")

prints:

I'm hungry!
I'm gonna eat:
banana
I'm gonna eat:
apple
I'm gonna eat:
kiwi
I love my life!


Assignment:

Add a for loop inside our code in the editor such that the final program would print:

Today we'll learn about:
Python
Java
JavaScript
Let's code!
STEP 1 OF 1
    Ctrl + Enter to check

    GO · FOR LOOPS - LOOPING OVER ARRAYS

    Exercise Create A For Loop in Go, explained

    What this lesson is about

    A Go program runs from the first line to the last, one statement at a time. This order is called the execution flow. A loop changes it: the statements inside its braces run again and again, once for each element, and then the program carries on with the line after the closing brace.

    The key question for every line near a loop is simple: is it inside the braces or outside them? Lines inside run once per element. Lines outside run once.

    Inside and outside the braces

    Go uses braces ({}) to mark the body of a loop. Here both calls to fmt.Println are in the body:

    languages := []string{"Python", "Java", "JavaScript"}
    
    for _, language := range languages {
        fmt.Println("I love " + language)
        fmt.Println("I want to get better at it")
    }
    

    The loop has three elements, so the body runs three times and prints six lines, two for each language:

    I love Python
    I want to get better at it
    I love Java
    I want to get better at it
    I love JavaScript
    I want to get better at it
    

    If the second call moves below the closing brace, it is no longer part of the loop:

    languages := []string{"Python", "Java", "JavaScript"}
    
    for _, language := range languages {
        fmt.Println("I love " + language)
    }
    fmt.Println("I want to get better at them")
    

    Now the loop prints one line per language, and the last line is printed once, after the loop has finished:

    I love Python
    I love Java
    I love JavaScript
    I want to get better at them
    

    Indentation helps you read this, but in Go the braces decide. The compiler does not care how a line is indented.

    Reading the flow top to bottom

    Take this program and follow it line by line:

    fruits := []string{"banana", "apple", "kiwi"}
    
    fmt.Println("I'm hungry!")
    
    for _, fruit := range fruits {
        fmt.Println("I'm gonna eat:")
        fmt.Println(fruit)
    }
    
    fmt.Println("I love my life!")
    

    First the slice is created. Then I'm hungry! is printed once. The loop runs its two lines for banana, then for apple, then for kiwi. When the elements run out, the flow moves to the last line, which prints once:

    I'm hungry!
    I'm gonna eat:
    banana
    I'm gonna eat:
    apple
    I'm gonna eat:
    kiwi
    I love my life!
    

    The range loop in Go

    The loop header for _, language := range languages has three parts:

    • range languages walks over the slice from the first element to the last.
    • On each pass, range gives two values: the index of the element and the element itself.
    • language receives the element on each pass. The blank identifier _ receives the index and throws it away.

    The _ is not decoration. Go refuses to compile a program with a variable that is declared and never used, so naming an index you do not need would be an error. Writing _ says that you are ignoring it on purpose.

    Also note that the loop variable exists only inside the loop. A line after the closing brace cannot use language.

    The exercise

    The editor holds a slice of languages and two prints, one before the gap and one after it:

    languages := []string{"Python", "Java", "JavaScript"}
    
    fmt.Println("Today we'll learn about:")
    
    // Write the for loop below:
    
    
    fmt.Println("Let's code!")
    

    The goal is to print the heading, then one language per line, then the closing message. Work through it in three decisions:

    1. The language names must come between the two existing prints, so the loop goes in the gap. That way the heading prints first and the closing message prints last.
    2. The loop needs to visit every element, so use range languages and discard the index with _.
    3. The body is one line that prints the current element. The closing message stays outside, because it must appear once.

    The finished program:

    languages := []string{"Python", "Java", "JavaScript"}
    
    fmt.Println("Today we'll learn about:")
    
    // Write the for loop below:
    for _, language := range languages {
        fmt.Println(language)
    }
    
    fmt.Println("Let's code!")
    

    Its output is the heading, the three names and the closing line:

    Today we'll learn about:
    Python
    Java
    JavaScript
    Let's code!
    

    Common mistakes

    • Putting the closing print inside the braces. It then prints three times, once after each language.
    • Putting the loop above the heading. The names then appear before the line that introduces them.
    • Writing for i, language := range languages and never using i. Go reports declared and not used.
    • Using the loop variable after the closing brace. It is out of scope there.

    Key takeaways

    • Statements run from top to bottom, and a loop repeats the lines in its braces.
    • Lines inside the braces run once per element. Lines outside run once.
    • range gives the index and the element, and _ discards what you do not need.
    • To check what a program prints, trace it line by line and count how many times each line runs.
    Keep going with GoAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free