
Control Flow in Golang: if, for, switch & defer
Control flow determines how your program makes decisions, handles loops, and controls execution order.
In real backend services—authentication, validation, routing, middleware, DB operations—control flow constructs appear everywhere.
Go keeps these constructs simple, predictable, and highly consistent.
1. if Statements
Go’s if statements do not require parentheses and support an optional initialization statement.
1.1 Basic if usage
age := 20
if age >= 18 {
fmt.Println("Allowed")
}
1.2 if-else
if age >= 18 {
fmt.Println("Adult")
} else {
fmt.Println("Minor")
}
1.3 if with initialization
Very common in backend code (e.g., database or cache lookups):
if user, err := repo.GetUser(id); err == nil {
fmt.Println("Found:", user.Name)
} else {
fmt.Println("User not found")
}
2. for Loops
Go has only one loop keyword: for.
It covers classic loops, while-loops, and infinite loops.
2.1 Classic counter loop
for i := 0; i < 5; i++ {
fmt.Println(i)
}
2.2 Range loop (important for backend models and DTOs)
users := []string{"alice", "bob"}
for index, name := range users {
fmt.Println(index, name)
}
Used everywhere when iterating JSON payloads, DB results, configs, etc.
2.3 Infinite loop
Used in workers, consumers, schedulers:
for {
processJob()
}
3. switch Statements
More powerful than other languages — supports conditions, multiple cases, type switches, and more.
3.1 Basic switch
status := 200
switch status {
case 200:
fmt.Println("OK")
case 400:
fmt.Println("Bad Request")
default:
fmt.Println("Unknown")
}
3.2 Multiple matches
switch ext := "jpg"; ext {
case "jpg", "jpeg":
fmt.Println("Image file")
case "mp4":
fmt.Println("Video file")
default:
fmt.Println("Other type")
}
3.3 Type switch
Used for handling interfaces in backend systems.
func printType(v interface{}) {
switch v.(type) {
case int:
fmt.Println("Integer")
case string:
fmt.Println("String")
default:
fmt.Println("Unknown")
}
}
4. defer
defer schedules a function to run after the current function finishes, similar to a “finally” block.
Used extensively in backend systems for:
- closing DB connections
- releasing locks
- closing file handles
- logging
4.1 Basic example
func readFile() {
f, _ := os.Open("data.txt")
defer f.Close() // always runs at the end
fmt.Println("Reading file...")
}
4.2 Multiple defers execute LIFO
defer fmt.Println("first")
defer fmt.Println("second")
Output:
second
first
5. Summary
In Part 4, you learned how Golang handles control flow using:
✔ if and if with initialization
✔ All versions of for loops
✔ switch for values and types
✔ defer for resource cleanup
These constructs appear constantly in production backend development.
