What the code is supposed to do
The program should greet every student in the students slice, printing one line each:
Welcome, Andy
Welcome, Sally
Welcome, John
The code you start with doesn't compile, so nothing is printed at all:
students := []string{"Andy", "Sally", "John"}
for _, name := range students {
}
fmt.Println("Welcome, " + student)
What goes wrong
The compiler reports two errors, and they come from two separate mistakes.
- The print sits after the loop. The braces of the loop are empty, so the body does nothing. The
fmt.Printlnline comes after the closing brace, which means it would run once, after the loop has finished. Even a version that compiled would print a single greeting instead of three. - The names don't match. The loop declares the variable
name, but the print line usesstudent, which doesn't exist. The compiler saysundefined: student. The loop variable also is never used, so it addsname declared and not used. Go rejects unused variables outright, instead of warning about them.
Compiling the starting code shows both messages together:
name declared and not used
undefined: student
Moving the print inside the braces alone would still fail, because student is still undefined and name is still unused. Both problems have to be fixed.
Scope: why the braces matter
The loop variable exists only inside the loop's braces. Outside them, name is not defined, so the print line couldn't use it even if the spelling matched. Everything that should happen once per student has to go between the braces, because only the body is repeated. Indentation is just for readers. Go's gofmt tool indents the body, but the braces are what the compiler follows.
Fixing it step by step
- Move the print inside the loop. Put the
fmt.Printlnline between the braces, so it runs for each student. - Make the names agree. Either rename the loop variable to
student, or change the print line to usename. The two spellings must be identical, since Go is case-sensitive. - Check that the variable is used. Once the print line inside the body uses the loop variable, the unused-variable error disappears.
The fixed code in Go
students := []string{"Andy", "Sally", "John"}
for _, student := range students {
fmt.Println("Welcome, " + student)
}
Here the loop variable is renamed to match the print line. Keeping name in the header and writing "Welcome, " + name is equally correct. Which name reads better is a style choice, and student says more about what each element is.
The _ in the header stands for the index, which this loop doesn't need. Without the underscore, an index variable that is never used would be a compile error of its own.
Common mistakes
- Fixing only one problem. Moving the print inside the loop while leaving the mismatched names still fails to compile. Renaming while leaving the print outside leaves a variable out of scope.
- Different capitalisation.
Studentandstudentare different names in Go. - Dropping the variable. Printing a fixed text such as
"Welcome, Andy"would compile, but it prints the same name every time.
Checking your fix
Run the code in the editor above. A correct fix compiles and prints the three greetings in order, one per line. If you still see an error, read the line and column in the message: it points at the exact variable the compiler can't match.