July 7, 2026

Go Control Flow – if, else, switch, and for Loops

Updated July 2, 2026. Refreshed for Go 1.22+ and current SEO best practices.

In this lesson we cover Go control flow — how programs make decisions and repeat work. You will learn go if else for loop patterns that appear in every real Go codebase: branching with if and switch, and iterating with for in its classic, while-style, and range forms. If you completed Lesson 4 – Variables and Types, you already know how to store data; now we act on it.

Prerequisites: Lessons 1–4 of this series, especially Variables and Types and Basic Syntax. Estimated time: 40–50 minutes.

1. if and else Statements

The if statement runs a block when a condition is true. Go requires parentheses around the condition — unlike C — but does not require parentheses around the condition expression itself:

package main

import "fmt"

func main() {
	score := 85

	if score >= 90 {
		fmt.Println("Grade: A")
	} else if score >= 80 {
		fmt.Println("Grade: B")
	} else {
		fmt.Println("Grade: C or below")
	}
}

Key rules: the opening brace { must be on the same line as if (Go enforces this). Conditions must be boolean expressions — Go will not treat 0 or "" as false the way some languages do. This strictness prevents subtle bugs and makes intent obvious when you read code.

2. if with a Short Statement

Go allows a short statement before the condition, separated by a semicolon. The variable declared in that statement is scoped only to the if block (and its else branches):

package main

import (
	"fmt"
	"math"
)

func main() {
	x := 16.0

	if root := math.Sqrt(x); root > 3 {
		fmt.Printf("Square root %.2f is greater than 3\n", root)
	} else {
		fmt.Printf("Square root %.2f is 3 or less\n", root)
	}
	// root is not visible here
}

This pattern is idiomatic when you need a temporary value only for the decision — for example, parsing input or calling a function that returns a result and an error. You will see if err := doSomething(); err != nil { ... } throughout Go code; we explore that error-handling style more when we cover functions.

3. switch Statements

switch compares a value against multiple cases. Unlike C, Go cases do not fall through unless you use fallthrough:

package main

import "fmt"

func main() {
	day := "Wednesday"

	switch day {
	case "Monday", "Tuesday", "Wednesday", "Thursday", "Friday":
		fmt.Println("Weekday")
	case "Saturday", "Sunday":
		fmt.Println("Weekend")
	default:
		fmt.Println("Unknown day")
	}
}

Go also supports switch without a tag — each case is a boolean expression, useful as a cleaner alternative to long if else chains:

score := 72

switch {
case score >= 90:
	fmt.Println("Excellent")
case score >= 70:
	fmt.Println("Good")
default:
	fmt.Println("Keep practicing")
}

Switch cases can use constants, strings, integers, and more. Because there is no automatic fall-through, you rarely need break — one less source of errors compared to C-style switches.

4. Classic for Loop

Go has one loop keyword: for. The classic three-part form mirrors C:

package main

import "fmt"

func main() {
	sum := 0
	for i := 1; i <= 5; i++ {
		sum += i
	}
	fmt.Println("Sum 1..5 =", sum) // 15
}

The init statement, condition, and post statement are all optional. An infinite loop is written as for { } — use break inside to exit. Unlike Python's for i in range(n), Go's C-style loop gives you full control over the counter variable and step size.

5. While-Style for Loop

Go has no while keyword. A condition-only for loop acts like while in other languages:

package main

import "fmt"

func main() {
	n := 1
	for n < 100 {
		n *= 2
	}
	fmt.Println("First power of 2 >= 100:", n) // 128
}

This form is common when you do not know how many iterations you need in advance — reading from a buffer, retrying a network call, or processing until a sentinel value appears. Combine with break and continue to skip the rest of an iteration or exit the loop early.

6. for range Loop

The range keyword iterates over slices, arrays, strings, maps, and channels. For a slice or array, you get an index and a copy of each element:

package main

import "fmt"

func main() {
	languages := []string{"Go", "Python", "Rust"}

	for index, lang := range languages {
		fmt.Printf("%d: %s\n", index, lang)
	}

	// Index only — discard value with _
	for i := range languages {
		fmt.Println(i, languages[i])
	}
}

When ranging over a string, the index is a byte offset and the value is a rune (Unicode code point). For maps, range yields key-value pairs in random order. We cover slices and maps in depth in later lessons; for now, treat range as the idiomatic way to visit every item in a collection.

7. Choosing the Right Construct

Use this quick reference when deciding which control structure fits:

Goal Construct Example
Two-way branch if else if x > 0 { ... } else { ... }
Scoped temp before test if short statement if v := f(); v > 0 { ... }
Many discrete values switch switch day { case "Mon": ... }
Counted iteration Classic for for i := 0; i < n; i++ { ... }
Condition-driven loop While-style for for condition { ... }
Collection iteration for range for i, v := range items { ... }

Go favors simplicity: one loop keyword, explicit conditions, and no hidden truthiness. If you learned control flow in Python, notice that Go's for range is the closest equivalent to for item in collection, while counted loops use the three-part for form instead of range(n).

8. Next Steps

You now understand go if else for loop control flow: branching, switch, and every form of the for loop. In the next lesson we cover functions — how to organize code into reusable blocks with parameters, return values, and defer.

Continue the series: Lesson 4 – Variables and Types · Lesson 6 – Functions

Browse all tutorials: Content Directory · Go Programming Hub

Frequently Asked Questions

Does Go have a while loop?
No. Use for condition { } without init or post statements. It behaves exactly like a while loop in other languages.

Do switch cases fall through in Go?
No, by default. Each case runs only its own block and then exits the switch. Use fallthrough explicitly if you truly need C-style fall-through — which is rare.

Can I modify the loop variable in a range loop?
The range value is a copy of each element. Changing it does not update the underlying slice. Use the index form for i := range s { s[i] = ... } to modify slice elements.

Want live Go or backend classes? Join Alkademy for instructor-led programming courses with hands-on projects.


0 0 votes
Article Rating
Subscribe
Notify of
1 Comment
Oldest
Newest Most Voted
trackback

[…] Previous: Lesson 5: Go Control Flow – if, else, switch, and for Loops […]

1
0
Would love your thoughts, please comment.x
()
x