What the code is supposed to do
The function printSum receives a slice of integers, nums, and should print the sum of all its numbers once. The program calls it with []int{1, 2, 3}, so the expected output is a single line: 6.
The starting code compiles and runs, but it prints 1, 2 and 3 on three separate lines. The task says there are two mistakes, and both are visible in how the loop is written.
func printSum(nums []int) {
for _, num := range nums {
sum := 0
sum += num
fmt.Println(sum)
}
}
What goes wrong
Trace the loop by hand for 1, 2, 3. On each pass, num holds the current element and the body runs from top to bottom:
- With
numequal to 1, a newsumis created with the value 0, 1 is added to it, and 1 is printed. - With
numequal to 2, another newsumstarts at 0, becomes 2, and 2 is printed. - With
numequal to 3, the same happens and 3 is printed.
The two mistakes are:
- The total is reset on every pass. The statement
sum := 0sits inside the loop body. Every time the body runs, Go declares a fresh variable calledsumand the previous one is gone. A running total has to survive from one iteration to the next, so it must be declared before the loop. - The print is inside the loop.
fmt.Println(sum)runs once per element. The total is only complete after the last element has been added, so the print belongs after the loop.
Fixing only one of them still gives a wrong result. With the declaration moved out but the print left inside, the output would be the running totals 1, 3 and 6. With the print moved out but the declaration left inside, sum would not even exist after the loop, and the code would not compile.
Fixing it step by step
- Move the declaration above the loop. Write
sum := 0before theforline. Now there is one variable, and it starts at 0 exactly once. - Keep the addition inside the loop.
sum += numis correct. It adds the current element to the samesumon every pass. - Move the print below the loop. Put
fmt.Println(sum)after the closing brace of thefor. It runs once, after every element has been added. - Leave
mainFunctionalone. The callprintSum([]int{1, 2, 3})is not part of the bug.
The fixed code in Go
func printSum(nums []int) {
sum := 0
for _, num := range nums {
sum += num
}
fmt.Println(sum)
}
func mainFunction() {
printSum([]int{1, 2, 3})
}
A few Go details are worth knowing here:
- Scope is set by braces. A variable declared with
:=exists only inside the block where it was declared, up to the closing brace. A variable declared inside the loop body is created again on each iteration. A variable declared before the loop lives for the whole loop and after it. for _, num := range nums. Arangeloop over a slice gives two values per iteration, the index and the element. The blank identifier_discards the index, because Go rejects variables that are declared and never used.- The sum is an
int.sum := 0infers the typeintfrom the literal, which matches the type of the elements. Adding anintto a different integer type would not compile. - An empty slice is fine. The loop body never runs, so the function prints
0.
Common mistakes
- Re-declaring with
:=inside the loop. Even ifsum := 0exists before the loop, writingsum := sum + numinside the loop body creates a new, innersumthat hides the outer one. The outer total stays 0. Usesum += numorsum = sum + numto update the existing variable. - Printing in the wrong place. A print inside the loop produces one line per element. Check the output as well as the final number.
- Starting from the first element. Setting
sum := nums[0]and then looping over everything adds the first element twice, and it panics on an empty slice. Starting at 0 is safe for every input.
Testing
[]int{1, 2, 3}prints6.[]int{-4, 4}prints0.[]int{}prints0.