Start learning free

LESSON 126 OF 338 · LOOPS & CONDITIONALS

Print Even Numbers in Go: Fixing the Buggy Code

Practice Read the full explanation

Inside the code editor we've tried to write a function that takes an array nums as argument and prints to the console the even numbers from that array.

So when we called printEvenNumbers({2, 1, 0, 4, 3}), we expected our code to print:

2
0
4

but it seems like we made some mistakes because when we run our code, it prints:

even
even

Assignment:

Your task is to fix our function such that it prints the even numbers from the array.

STEP 1 OF 1
    Ctrl + Enter to check

    GO · LOOPS & CONDITIONALS

    Buggy Code Print Even Numbers in Go, explained

    What the code is supposed to do

    The function printEvenNumbers takes a slice nums and should print the even numbers from it, one per line. For the call printEvenNumbers([]int{2, 1, 0, 4, 3}), the expected output is 2, 0 and 4, in the order they appear in the slice.

    The code you start with compiles, but it prints the word even twice instead:

    func printEvenNumbers(nums []int) {
        for _, num := range nums {
            if num % 2 == 1 {
                fmt.Println("even")
            }
        }
    }
    
    // Do not change this code:
    func mainFunction() {
        printEvenNumbers([]int{2, 1, 0, 4, 3})
    }
    

    What goes wrong

    There are two separate mistakes, both inside the loop.

    The test selects the wrong numbers

    The operator % gives the remainder after division. An even number divides by 2 with nothing left over, so its remainder is 0. An odd number leaves remainder 1. The condition num % 2 == 1 is therefore true for odd numbers. In the example, that is 1 and 3, which is exactly why the output has two lines: one for each odd number in the slice. The even numbers 2, 0 and 4 fail the test and are skipped.

    The fix is to compare with 0: num % 2 == 0.

    The print shows a word, not the number

    The text "even" in quotes is a string literal, and Go prints it exactly as written on every pass. It never looks at num. To print the number, pass the variable itself, without quotes: fmt.Println(num).

    Fixing it step by step

    1. Change the test from num % 2 == 1 to num % 2 == 0, so that the body runs for even numbers.
    2. Change the print from the string "even" to the variable num.
    3. Leave everything else alone. The loop, the signature and the mainFunction that makes the call stay as they are.

    The fixed code in Go

    func printEvenNumbers(nums []int) {
        for _, num := range nums {
            if num % 2 == 0 {
                fmt.Println(num)
            }
        }
    }
    
    
    func mainFunction() {
        printEvenNumbers([]int{2, 1, 0, 4, 3})
    }
    

    Tracing the call: 2 gives remainder 0 and is printed; 1 gives 1 and is skipped; 0 gives 0 and is printed; 4 is printed; 3 is skipped. The output is 2, 0, 4.

    A few Go details:

    • Zero is even. 0 % 2 is 0, so it is printed.
    • The slice literal. []int{2, 1, 0, 4, 3} creates a slice of five integers. The type goes before the braces.
    • Why _. range yields an index and a value. The index is not needed, and Go would refuse to compile an unused variable, so it is discarded.
    • Negative numbers. In Go, % takes the sign of the left operand, so -3 % 2 is -1, not 1. That makes num % 2 == 1 a poor odd test for negative numbers, while num % 2 == 0 is correct for evens of either sign.

    How to spot this kind of bug

    Read the broken output against the expected one. Two lines of even instead of three numbers tells you two things at once: the count is wrong, so the condition selects the wrong elements, and the content is wrong, so the print isn't showing the variable. When the number of output lines matches the number of elements the test accepts, count how many elements of the input pass it. Here the odd numbers are 1 and 3, which is exactly two lines. Checking the output size against the input is a quick way to separate a faulty condition from a faulty print.

    Common mistakes

    • Fixing only one of the two bugs. Changing the condition alone would print even three times. Changing the print alone would print 1 and 3.
    • Putting quotes around num. fmt.Println("num") prints the word num.
    • Using / instead of %. Division gives the quotient, which is not what the test needs.
    • Using == 1 for odd numbers on negative input. The remainder of -3 divided by 2 is -1, so the test misses it. Compare with 0, or use != 0 for odd.

    Checking your fix

    With the corrected function, the call in mainFunction prints three lines: 2, 0 and 4. Also try []int{-4, -3, 7}: only -4 is printed.

    Keep going with GoAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free