Skip to main content

Command Palette

Search for a command to run...

Control Flow Notes

Updated
7 min read

Challenges:

  • Not knowing what kind of problem I was solving.

  • I can think of possible ways and ideas to solve problems, but putting them together in a logical sequence is the challenge.

  • Mental pressure to solve, trying to code before having clarity

  • Learning tools without concepts

What I learnt

Control flow is basically about decision + repetition

  • loop (for / while-style) = tracking, repetition

  • conditions (if / else, true or false)

  • continue/break = when to skip or stop

  • nesting (loops inside loops)

  • state = memory

  • decision = transition

Also learned how to:

  • pause/calm before coding

  • classify the problem

  • choose tools intentionally (flexible)

  • separate problem type from syntax, they are not the same.

3 Core Control Flow Moves

Sequence: Running instructions from top to bottom.

Decision (Branching): “If this is true, do A. Otherwise, do B.”

I realize that if does not belong to loops, it can exist anywhere (outside or inside), loops just repeat decisions, thats all.

Repetition (Loops): Keep doing this while a condition is true.

Types of Loops

  • Classic for Loop: when I know the count, how many times the program should run.

Examples are print 1 to 10, iterate over array indices, fixed grid sizes

for i := 1; i <= 10; i++ {
     fmt.Println(i)
}
  • i = starts

  • condition is checked

  • body runs

  • i changes

  • repeat

If the condition is false at any point, loop stops.

i == max is WRONG, == means *only when exactly equal*
i <= max is CORRECT, <= means *until it reaches*
  • While-Style Loop: when I don’t know the count, or how many times the program will run or user will input

Examples are:

user input, password attempts, read until 0, read until "done"

for n != 0 {
     fmt.Scan(&n)
}

With while-loop, there is no counter, no increment section, only a condition. It’s more flexible.

Control Flow Patterns/Concepts

  1. Counter Loop: How many times, used when the number of iterations matters more than the values.

Thought process

  • Something to happen in a fixed number of times, it’s about the count

  • A counter starts somewhere, usually 0 or 1

  • It changes predictably

  • The loop ends when the count is reached

Example task

  • Print the first 10 numbers

  • Print 8 odd numbers

  • Repeat an action 5 times

  • Print the first 8 odd numbers.

Reasoning

  • I need 8 outputs → counter

  • Odd numbers → start at 1

  • Next odd = +2

  • Stop after 8 prints

Code for (Print the first 8 odd numbers.)

count := 0

for i := 1; count < 8; i += 2 {
        fmt.Println(i)
        count++
}

Note: loop variable (i) and the reason for stopping (counter) do NOT have to be the same thing, because an external counter is required here to get cleaner output.

  1. Sentinel Loop: Run until something happens. Important concept in While-loop.

Thought process

  • Don’t know how many times, stop when there’s a signal.

  • The signal is the sentinel, can 0, negative number, "stop", “done”, etc.

  • Read input

  • Check sentinel condition

  • Continue until sentinel appears

  • What matters is not the loop, it’s the sentinel condition.

Example task

Read numbers until the user enters 0.

Reasoning

  • Does not matter how many numbers or times the user inputs

  • If it is 0, stop

  • Everything else continues

Code

var n int

fmt.Scan(&n)

for n != 0 { // if n is not 0, continue to print n, stop when n is 0
        fmt.Println(n)
        fmt.Scan(&n)
}

Note: The loop condition is the stopping logic, not an if (which can also be used in this case). If the condition is false, the loop doesn’t run. I don’t need break if the condition already encodes the stop. This was a shift for me, and I got it.

  1. Accumulator: compressing many values into one result.

Thought process

  • Every input matters, but only keep a summary.

  • Sum, count, max, min, and average all are same family.

  • Initialize accumulator

  • Update it every iteration

  • Use comparison or addition

Example task A: Sum

Sum numbers until 0.

sum := 0
var n int

fmt.Scan(&n)

for n != 0 {
        sum += n
        fmt.Scan(&n)
}

Example task B: Max (this one confused me, rightly)

Read numbers until 0 and find the max.

Reasoning

  • No input is deleted or skipped

  • Every number is read/compared

  • I keep one running value

  • Sentinel loop, running comparison, store single value

Code

var n int

fmt.Scan(&n)
max := n

for n != 0 {
        if n > max {
            max = n
        }
    fmt.Scan(&n)
}

Note: Finding max/min is not filtering, because I am not removing any input, I’m comparing every input against a stored state. It is a running comparison, a form of accumulation.

  1. Filter: Some inputs don’t participate, different from accumulation.

Thought process

  • Ignore some values.

  • If & continue needed here.

  • Read input

  • Test condition

  • Skip or select

Example tasks

  • Ignore negatives

  • Skip multiples of 3

  • Count only evens

  • Ignore values in a range

  • Count even numbers until 0.

Code for (Count even numbers until 0)

count := 0
var n int

fmt.Scan(&n)

for n != 0 {
        if n % 2 != 0 {
                fmt.Scan(&n)
                continue
        }
        count++ (external counter)
        fmt.Scan(&n)
}

Note: Filtering means some inputs are discarded, which is different from max/min, where all inputs participate (accumulation).

  1. Step Loop: Jumping with intention

Thought process

  • The sequence itself has a pattern.

  • Loop + “if” can be used but cleaner is “controlled stepping”

  • No filtering needed

  • Skipping is needed

Example task

  • Even numbers

  • Countdown by 2s

// Print multiples of 5 from 5 to 50.
for i := 5; i <= 50; i += 5 { // skip/jump: “i += 5”
        fmt.Println(i)
}

Note: If the pattern is numeric, encode it in the step, not with if.

  1. Shifting/Top-N: Keep the best few (this was stateful)

Thought process

  • Keeping the ranked state is important

  • Best 3 values seen so far.

  • Compare

  • Shift values down (reassignment)

  • Insert at the top (preserve the order)

Example task

Concept (not code)

// Track top 3 numbers entered.
new > first → shift (first → second → third)
new > second → shift
new > third → replace

Note: This is controlled mutation. It builds on max/min, but extended with shifts & slots

  1. Nested Loops: Multiple dimensions (it clicked when I stopped thinking of them as “nested” but as outer loop & inner loop)

Thought process

  • The first loop is the row, another is the column.

  • Row loop defines context, time periods, column defines the relationship, it repeats within it

  • Outer loop = big picture

  • Inner loop = repeated detail

Example task

// Print a 4×4 grid. 
for row := 1; row <= 4; row++ {
        for col := 1; col <= 4; col++ {
                fmt.Print("*")
        }
    fmt.Println()
}

// Example 2: multiplication table.
for row := 1; row <= 10; row++ {
    for col := 1; col <= 10; col++ {
        fmt.Printf("%d x %d = %d\\n", row, col, row*col)
    }
}

Note: Nested loops are not difficult, they’re just layered repetition. The inner loop completes before outer loop continues.

  1. Map-Based Uniqueness: Something seen before, memory needed not repetition

Thought process

  • Memory needed.

  • Map for tracking

  • Loop for reading

  • Conditional check

  • Past inputs matter

  • Uniqueness matters

Example task

Count unique numbers entered.

seen := make(map[int]bool)
var n int

fmt.Scan(&n)
        for n != 0 {
                if !seen[n] {
                seen[n] = true
        }
    fmt.Scan(&n)
}

Producer vs Consumer Loops (this was a good realization, I picked up from learning this pattern) The third loop in Go, “for-range”, is for consuming existing data. while-style for is for producing data. Producer loop You are creating a new data from the input:

for input != "done" {
    fmt.Scan(&input)
}

Consumer loop You are using (iterating through) an existing data:

for _, name := range names {
    fmt.Println(name)
}

Note: When loops alone aren’t enough, data structures enter. The loop needs to remember what it has already seen, and the map keeps track.


Now I understand that Control flow is not just about writing loops, it’s about recognizing repetition, decisions, state, and stopping conditions.

Before writing any for or if code, I pause and answer the following questions, to know the tools and concepts required.

  1. What kind of problem is this (Repetition? Decision? Accumulation? Selection? Ranking Memory?)

  2. Am I repeating something, tracking something, or deciding something?

  3. What state must I remember while the program runs?

  4. What event or condition stops this process?

Every control-flow problem fits into one or more of these.