The bug
The program should print this:
What a nice day!
Hey, Andy
How are you?
Hey, Mike
How are you?
Hey, Mary
How are you?
Let's start the class!
This version has several mistakes at once:
students := []string{"Andy", "Mike", "Mary"}
fmt.Println("Let's start the class!")
for _, student := range students {
fmt.Println("What a nice day!")
}
fmt.Println("How are you?")
fmt.Println("Hey, " + student)
It does not even run, because the compiler rejects it with two errors:
student declared and not used
undefined: student
Reading the two compiler errors
The first error points at the loop header. student is declared there, but nothing in the loop body uses it, and Go does not allow an unused variable.
The second error points at the last line. The variable student only exists between the loop's braces, so after the closing brace the name is undefined. The line that wants it is in the wrong place, outside the loop. The two errors have one cause: the greeting that uses student is outside the loop.
Comparing with the expected output
Even after the compiler is happy, the logic is wrong. Look at the shape of the expected output:
- One line comes first and runs once:
What a nice day!. - Then a pair of lines repeats for each student:
Hey,plus the name, followed byHow are you?. - One line comes last and runs once:
Let's start the class!.
The buggy code has all of these in the wrong places. The closing message is at the top. What a nice day! is inside the loop, so it would repeat. How are you? is outside the loop, so it would print once.
The fix
Put each line where its count says it belongs: opening line before the loop, the two repeating lines inside it, closing line after it.
students := []string{"Andy", "Mike", "Mary"}
fmt.Println("What a nice day!")
for _, student := range students {
fmt.Println("Hey, " + student)
fmt.Println("How are you?")
}
fmt.Println("Let's start the class!")
The greeting is now in the loop, so student is both used and in scope. This removes both compiler errors. Inside the body, the order of the two prints decides the order of each pair: the greeting comes before the question.
Lessons from this bug
- Compiler messages often point at one mistake from two sides. Read both before changing anything.
- A loop variable lives only inside the loop body.
- Lines before the loop run first and once. Lines after it run last and once. Lines inside run once per element.
- Start from the expected output and mark which lines repeat. That tells you what the loop body is.
Tracing the fixed version
The program prints What a nice day! and then enters the loop. For Andy it prints the greeting and the question, then it does the same for Mike and for Mary. When the slice is exhausted, the loop ends and the last line prints the closing message. That is eight lines in total, in the order the expected output shows.
Why the order inside the loop matters
If you swapped the two prints in the body, each pair would read How are you? followed by Hey, Andy, and the output would no longer match. Within one pass the lines run in the order they are written, so that order is part of the answer too.
A method for mixed bugs
When a program has several mistakes, do not fix them one by one at random. First write the expected output as a list of lines. Next mark each line as once-at-the-start, repeated, or once-at-the-end. Then arrange the code in the same three zones and check that every repeated line only uses names that exist inside the loop. This takes a minute and avoids the cycle of fixing one compiler error and meeting the next.