Start learning free

LESSON 128 OF 338 · LOOPS & CONDITIONALS

Print Odd 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 a number n as argument and prints to the console the odd numbers from 0 through n.

So when we called printOddNumbers(8), we expected our code to print:

1
3
5
7

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


Assignment:

Your task is to fix our function such that it prints the odd numbers from 0 through n.

STEP 1 OF 1
    Ctrl + Enter to check

    GO · LOOPS & CONDITIONALS

    Buggy Code Print Odd Numbers in Go, explained

    What the code is supposed to do

    The function printOddNumbers takes a number n and should print the odd numbers smaller than n, one per line. The call printOddNumbers(8) should print 1, 3, 5 and 7. The number 8 itself is even, and the loop stops before reaching it.

    The code you start with compiles, but it prints nothing:

    func printOddNumbers(n int) {
        for i := 0; i < n; i++ {
            if n % 2 == 1 {
                fmt.Println(n)
            }
        }
    }
    
    // Do not change this code:
    func mainFunction() {
        printOddNumbers(8)
    }
    

    What goes wrong

    The loop header is correct: i goes from 0 to n - 1, which is 0 to 7. The problem is that the two lines inside the loop never use i. They use n, the parameter.

    The parameter n is 8, and it stays 8 for the entire run. Only i changes from pass to pass. So the test n % 2 == 1 asks the same question eight times, "is 8 odd?", and the answer is always no. The body never runs, which is why nothing is printed.

    Had n been odd, say 9, the opposite would happen. The test would always be true, and the function would print the number 9 nine times, once per pass. This bug is easy to miss because the loop still looks reasonable.

    Fixing it step by step

    1. Find the variable that changes. In this loop, it is i. The parameter n only sets where the loop stops.
    2. Test i in the condition. Change n % 2 == 1 to i % 2 == 1, so that each pass asks whether the current number is odd.
    3. Print i. Change fmt.Println(n) to fmt.Println(i), so that the odd number found is the one printed.

    The fixed code in Go

    func printOddNumbers(n int) {
        for i := 0; i < n; i++ {
            if i % 2 == 1 {
                fmt.Println(i)
            }
        }
    }
    
    
    func mainFunction() {
        printOddNumbers(8)
    }
    

    Tracing it with n = 8: 0 gives remainder 0 and is skipped, 1 gives remainder 1 and is printed, 2 is skipped, 3 is printed, and so on up to 7. The loop ends when i reaches 8, so the output is 1, 3, 5, 7.

    A few details about Go:

    • The compiler won't catch this. Both n and i are used, and the types are right. The program is valid, just wrong, so only running it reveals the problem.
    • The bound is exclusive. i < n stops at n - 1. If n were 7, the last odd number printed would be 5, not 7.
    • % and non-negative numbers. For the values 0 and above that this loop produces, a remainder of 1 means odd.

    How to spot this kind of bug

    When a loop prints nothing, or prints the same thing repeatedly, ask which variables the body actually reads. A loop variable that is declared in the header but never mentioned in the body is a warning sign, because the body then does the same work on every pass. Here i appears only in the header. In Go the compiler accepts this, since a variable used in a loop condition counts as used. Adding a temporary fmt.Println(i, n) inside the loop shows at once that i changes while n does not.

    Common mistakes

    • Fixing only one line. Changing the test to i % 2 == 1 but still printing n would print 8 four times.
    • Changing the loop instead. The header was never the problem. Rewriting it to i <= n adds an extra pass without fixing anything.
    • Starting from 1 and printing every number. Without the remainder test, even numbers would be printed too.
    • Using i / 2. Division gives a quotient. To find odd numbers, you need %.

    Checking your fix

    Run the corrected function and the output should be exactly four lines: 1, 3, 5 and 7. With n = 1 or n = 0, nothing is printed, because no odd number is smaller than 1.

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