What the code is supposed to do
The function printDouble takes a number and prints twice that number. The call printDouble(10) should print:
20
The code as given does not compile:
func printDouble(n int) {
fmt.Println(2 * num)
}
func mainFunction() {
printDouble(10)
}
The compiler stops with an error that ends in undefined: num.
What goes wrong
The parameter is called n. The body, however, multiplies by num, a name that was never declared. Go has no variable called num anywhere: not in the function, not in the file. When a name can't be found, the compiler reports undefined and names the identifier it could not resolve. Here it is num.
A function body can use only three kinds of names: its own parameters, the variables it declares itself, and package-level names such as other functions. The call printDouble(10) puts the value 10 into n. It does not create a num, whatever the argument is meant to represent.
How the value travels
It helps to follow the 10 through the program. In mainFunction, the call printDouble(10) hands the argument 10 to the function. At the start of the call Go creates the parameter n and stores 10 in it. The body then evaluates 2 * n, which is 20, and passes the result to Println.
The only link between the call and the body is the parameter's name. The caller can pass a literal, a variable with any name or a more complex expression, and the body always sees it under the name written in the header. This is why the body must use n even when the caller thinks of the value as "the number".
Fixing it step by step
- Read the error. It names
numas the undefined identifier and gives the line, which is thefmt.Printlnline. - Compare with the header. The header declares
n int. There is nonum. - Make the two names match. Either use
nin the body, or rename the parameter tonum. The first is the smaller change. - Check the call.
printDouble(10)passes oneint, which fits the singleintparameter, somainFunctionneeds no edit.
The fixed code in Go
func printDouble(n int) {
fmt.Println(2 * n)
}
func mainFunction() {
printDouble(10)
}
/* Explanation:
We got an error because inside the original function we used a variable "num", which is not the parameter "n", so it wasn't recognized.
One fix is to use "n" instead of "num" in the line "fmt.Println(2 * n)"
Another possible fix is to change the parameter name to "num", like this:
func printDouble(num int) {
fmt.Println(2 * num)
}
*/
Both fixes print 20. Some Go details:
- The type stays.
2 * nworks becausenis anintand the constant 2 takes that type. - Names are case-sensitive.
Nandnare different identifiers, so2 * Nwould be undefined too. - Parameters live inside their function. A name declared in
printDoublecan't be seen frommainFunction, and the reverse holds as well. - Printing numbers needs no conversion.
Printlnaccepts values of any type and prints anintas its digits.
Common mistakes
- Renaming in only one place. If you rename the parameter to
numbut leavensomewhere in the body, the error just moves toundefined: n. - Declaring
numinside the function. Adding a line such asnum := 10would silence the error but print the same number no matter what the caller passes. - Changing the call. The call is correct; edits there can't fix an undefined name in the body.
- Hardcoding 20.
fmt.Println(20)passes this call but ignores the parameter entirely.
Checking your fix
Run the code in the editor above. The program should compile and print 20. If a new error appears, read its identifier again: it names the exact spelling the compiler could not find.