Start learning free

LESSON 111 OF 338 · FOR LOOPS - LOOPING OVER ARRAYS

Buggy Code in Go: Moving a Line Out of a For Loop

Practice Read the full explanation

Inside the code editor we've tried to write a program that should print:

Hey, Andy
Hey, Mike
Hey, Mary
Let's start the class!

but it seems like we made some mistakes because when we run our code, it produces this output:

Hey, Andy
Let's start the class!
Hey, Mike
Let's start the class!
Hey, Mary
Let's start the class!

Assignment:

Your task is to fix our code such that it will print the desired output.

STEP 1 OF 1
    Ctrl + Enter to check

    GO · FOR LOOPS - LOOPING OVER ARRAYS

    Buggy Code For Loops Execution Flow 2 in Go, explained

    The bug

    The program should greet three students and then announce the class once:

    Hey, Andy
    Hey, Mike
    Hey, Mary
    Let's start the class!
    

    The code we start from is:

    students := []string{"Andy", "Mike", "Mary"}
    
    for _, student := range students {
        fmt.Println("Hey, " + student)
        fmt.Println("Let's start the class!")
    }
    

    It prints the announcement after every greeting:

    Hey, Andy
    Let's start the class!
    Hey, Mike
    Let's start the class!
    Hey, Mary
    Let's start the class!
    

    Why it happens

    The loop body is everything between the braces, and it runs once per element of students. Both fmt.Println calls sit in that body, so both run three times, in the order they are written. The first call uses student, so it belongs in the loop. The second never mentions student. It is a single announcement that should happen after the greetings are finished.

    The fix

    Close the loop right after the greeting, and put the announcement on the next line, outside the braces:

    students := []string{"Andy", "Mike", "Mary"}
    
    for _, student := range students {
        fmt.Println("Hey, " + student)
    }
    
    fmt.Println("Let's start the class!")
    

    Now the flow is: the loop visits Andy, Mike and Mary and prints a greeting for each. Once there are no more elements, the loop ends and the program moves on to the next line, which runs one time.

    The blank line is not what fixes it

    The blank line between the loop and the announcement is only for readability. What changed is the closing brace: it moved up so that it comes before the announcement. In Go the braces define the loop body, so moving a closing brace is exactly the kind of change that moves a statement in or out of a loop.

    Go details in this code

    • The blank identifier _ takes the index that range produces. Writing a name there that you never use would be a compile error.
    • The variable student exists only inside the loop. If you tried to print it after the closing brace, the compiler would say it is undefined.
    • The opening brace of for must be on the same line as the loop header. Go does not accept it on the next line.

    A quick check

    Ask of each line: how many times should it run? The greeting should run three times, once per student. The announcement should run once. Lines that run once go outside the braces, lines that run once per element go inside. This habit solves most loop-placement bugs before you run the code.

    Tracing both versions

    In the buggy version the pass for Andy prints the greeting and then the announcement. The pass for Mike does the same, and so does the pass for Mary. That is six lines, with the announcement appearing three times.

    In the fixed version each pass prints only a greeting, so the loop produces three lines. The program then reaches the announcement exactly once. Four lines in total, which matches the expected output.

    What if the slice changes?

    Suppose the class has five students. The fixed program prints five greetings and one announcement without any other edit. With an empty slice it skips the loop body entirely and still prints the announcement, which is the right behaviour for a class that starts whether or not anyone is listed.

    The opposite mistake

    The reverse bug is just as common: a line that needs the loop variable ends up outside the loop. If the greeting were placed after the closing brace, the compiler would complain that student is undefined, and the loop body would be left without a use for its variable. Go catches that one for you. A statement in the wrong place that does not use the loop variable, like the announcement here, compiles fine and only shows up as wrong output, so you have to catch it by comparing the output with what you expect.

    Keep going with GoAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free