Control Flow Notes
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,
trueorfalse)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
ifdoes 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
forLoop: 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
- 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.
- 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.
- 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.
- 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).
- 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.
- 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
- 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.
- 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.
What kind of problem is this (Repetition? Decision? Accumulation? Selection? Ranking Memory?)
Am I repeating something, tracking something, or deciding something?
What state must I remember while the program runs?
What event or condition stops this process?
Every control-flow problem fits into one or more of these.