What the code is supposed to do
The function welcomeUser takes a person's name and prints a welcome message for that person. mainFunction calls it twice, once for Andy and once for John, so the program should print two different lines:
Welcome, Andy!
Welcome, John!
This is the code you start with:
func welcomeUser(name string) {
fmt.Println("Welcome, Andy!")
}
func mainFunction() {
welcomeUser("Andy")
welcomeUser("John")
}
It compiles, but it prints Welcome, Andy! twice.
What goes wrong
The two calls pass different arguments, "Andy" and "John", and Go copies each one into the parameter name when the call starts. The parameter is there, and it holds the right value in each call. But the function body never reads it. The only statement in the body prints a string literal that already has the name Andy typed into it, so every call prints the same text no matter what it receives.
A parameter is a local variable that the caller fills in. It changes the output only when the body uses it. A hard-coded value in the body overrides whatever the caller sent.
Go doesn't complain here. An unused local variable is a compile error in Go, but an unused function parameter is allowed, so the compiler stays silent and the bug shows up only in the output.
Fixing it step by step
- Find the line that prints the greeting. It is the only line in
welcomeUser, and it contains the fixed name. - Split the text around the part that changes. The fixed pieces are
"Welcome, "and"!". The name goes between them. - Join the pieces with
+. Go concatenates strings with+, and it adds nothing between the parts, so the comma and the space belong to the first piece. - Leave
mainFunctionalone. The calls are correct. Only the function body needs to change.
The fixed code in Go
func welcomeUser(name string) {
fmt.Println("Welcome, " + name + "!")
}
func mainFunction() {
welcomeUser("Andy")
welcomeUser("John")
}
A few details about this fix:
- Both operands of
+must be strings. Herenameis astring, so the expression is valid. Go does not convert numbers to strings automatically, so"Welcome, " + 5would not compile. - Exact text matters. The comma after
Welcome, the space and the exclamation mark are all part of the expected output."Welcome " + namewould print something different. fmt.Printlnadds the line break. You don't need"\n"in the string.- Formatting is an alternative.
fmt.Printf("Welcome, %s!\n", name)prints the same line. Here you would have to write the line break yourself, becausePrintfdoesn't add one.
Seeing the difference
Trace the second call, welcomeUser("John"). Go sets name to "John" and runs the body. In the broken version the body never mentions name, so the value is set and then ignored. In the fixed version, the expression "Welcome, " + name + "!" is evaluated first, producing Welcome, John!, and only then does fmt.Println print it. The same body gives different output for each call because the parameter is part of what it computes.
Common mistakes
- Putting the name inside the quotes.
"Welcome, name!"is just text. It prints the wordname, not the value of the parameter. - Changing the calls instead of the function. Editing the arguments can't help when the function ignores them.
- Dropping the parameter. Removing
name stringfrom the header would make the calls fail to compile, because the calls pass an argument. - Forgetting a piece of the message. Leaving out the final
"!"givesWelcome, Andy, which doesn't match.
Checking your fix
Run the code in the editor above. A correct fix prints Welcome, Andy! on the first line and Welcome, John! on the second. If both lines are still the same, the body still contains a fixed name.