03. Control Flow in Go
🚀 Master the art of directing your Go programs! This guide breaks down essential control flow mechanisms like if-else, switch, for loops, and more, enabling you to write efficient and decision-driven code. 🎯
What we will learn in this post?
- 👉 If-Else Statements
- 👉 Switch Statements
- 👉 For Loops
- 👉 Range Keyword
- 👉 Break and Continue
- 👉 Goto and Labels
- 👉 Conclusion!
Conditional Statements in Go 🚀
Let’s dive into how Go handles conditional logic! Go uses if, if-else, and if-else-if statements to control the flow of your program based on conditions. The best part? No parentheses needed around your conditions, but braces {} are mandatory.
if Statement 🤔
The if statement executes a block of code only if a condition is true.
1
2
3
4
5
6
7
8
9
10
11
package main
import "fmt"
func main() {
age := 25
if age >= 18 {
fmt.Println("You are eligible to vote!")
}
}
if-else Statement ⚖️
The if-else statement executes one block of code if the condition is true and another block if it’s false.
1
2
3
4
5
6
7
8
9
10
11
12
13
package main
import "fmt"
func main() {
number := 7
if number%2 == 0 {
fmt.Println("Even number")
} else {
fmt.Println("Odd number")
}
}
if-else-if Statement 🪜
The if-else-if statement lets you check multiple conditions in sequence.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main
import "fmt"
func main() {
score := 75
if score >= 90 {
fmt.Println("Excellent!")
} else if score >= 70 {
fmt.Println("Good!")
} else {
fmt.Println("Needs improvement")
}
}
Short Statement Syntax 💫
Go provides a neat feature within if statements: the short statement. This allows you to declare and initialize a variable within the if condition itself.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main
import "fmt"
func main() {
if x := getValue(); x > 0 {
fmt.Println("Value is positive:", x)
} else {
fmt.Println("Value is not positive:", x)
}
}
func getValue() int {
return -5 // You can change this to test different values.
}
In this example, x := getValue() is executed before the condition x > 0 is evaluated. The variable x is only scoped to the if and else blocks.
- Key Takeaways:
- Go requires braces
{}. - Go doesn’t need parentheses around conditions
(). - The short statement syntax (
if x := ...; condition) is handy!
- Go requires braces
graph TD
A[Start] --> B{Condition 1?};
B -- True --> C[Execute Block 1];
B -- False --> D{Condition 2?};
D -- True --> E[Execute Block 2];
D -- False --> F[Execute Block 3];
C --> G[End];
E --> G;
F --> G;
More Information Resources:
Switch Statements in Go: A Simple Guide 🚦
Go’s switch statement is a clean way to handle multiple conditions. Think of it as a more powerful if-else if-else chain. The cool part? Go handles break for you!
Types of Switches ✨
Go provides different flavors of switch statements:
- Expression Switch: Evaluates an expression and matches its value against
casevalues.
1
2
3
4
5
6
7
8
9
grade := "B"
switch grade {
case "A":
println("Excellent!")
case "B":
println("Good job!")
default:
println("Keep trying!")
}
- Type Switch: Used to determine the type of a variable. Super handy when dealing with
interface{}.
1
2
3
4
5
6
7
8
9
var i interface{} = 10
switch v := i.(type) {
case int:
println("It's an integer:", v)
case string:
println("It's a string:", v)
default:
println("I don't know what it is!")
}
fallthrough Keyword 🍂
Normally, Go executes only the matching case and then automatically exits the switch. The fallthrough keyword makes execution continue to the next case, regardless of whether it matches.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
num := 2
switch num {
case 1:
println("One")
case 2:
println("Two")
fallthrough
case 3:
println("Three")
default:
println("Something else")
}
// Output:
// Two
// Three
Implicit break Behavior 👍
Go implicitly adds a break statement after each case. You don’t need to write break yourself. This helps prevent accidental fall-through bugs common in other languages.
Switch with no Expression 🔍
You can also write switch statements without an expression. This is similar to using a chain of if/else if statements.
1
2
3
4
5
6
7
8
9
age := 25
switch {
case age < 18:
println("Minor")
case age >= 18 && age < 65:
println("Adult")
default:
println("Senior")
}
Check out the official Go documentation here for even more details! 📖
Go’s Looping Powerhouse: The for Loop 🔄
Go keeps things simple! Instead of multiple loop types like while or do-while in other languages, Go rocks just one: the for loop. But don’t let that fool you; it’s super flexible and can handle all your looping needs.
Three Flavors of for 🍦
Traditional Three-Component for ⚙️
Like in C or Java, you’ve got initialization, condition, and post-statement, all in one line.
1
2
3
for i := 0; i < 5; i++ {
println(i) // Prints 0 to 4
}
- Use Case: Looping a specific number of times, like processing elements in a slice or array.
graph LR
A[Start] --> B[Initialize i]
B --> C{Is i < 5?}
C -- True --> D[Print i]
D --> E[Increment i]
E --> C
C -- False --> F[End]
While-Style for ⏳
Just a condition, like a while loop.
1
2
3
4
5
i := 0
for i < 5 {
println(i)
i++
}
- Use Case: Looping until a condition is met, perhaps reading from a stream or waiting for an event.
Infinite Loop ♾️
No condition at all! Keep going until you break out.
1
2
3
4
5
6
for {
// Do something
if someCondition {
break // Exit the loop
}
}
- Use Case: Servers listening for incoming connections, or background processes running continuously.
You can find more information about Go for loops in the official Go documentation.
The Magic of range in Go 🪄
The range keyword in Go is your friendly iterator! It makes looping through data structures easy peasy. Think of it as a helper that automatically gives you both the index and the value of each item.
range across Different Data Structures 🧰
Let’s explore how range works with various data types:
Arrays and Slices:
1 2 3 4
numbers := []int{10, 20, 30} for index, value := range numbers { fmt.Printf("Index: %d, Value: %d\n", index, value) }
Here,
indexrepresents the position (0, 1, 2) andvalueis the element at that position.Maps:
1 2 3 4
ages := map[string]int{"Alice": 30, "Bob": 25} for name, age := range ages { fmt.Printf("Name: %s, Age: %d\n", name, age) }
namebecomes the key, andageis the value associated with that key.Strings:
1 2 3 4
word := "Hello" for index, runeValue := range word { fmt.Printf("Index: %d, Rune: %c\n", index, runeValue) }
Important Note:
rangeon strings iterates over runes, which are Unicode code points (like characters).Channels:
1 2 3 4 5 6 7 8
ch := make(chan int, 3) ch <- 1 ch <- 2 close(ch) // important for channels for value := range ch { fmt.Println("Received:", value) }
rangereceives values from the channel until it’s closed.
Ignoring Values with _ 🤫
Sometimes, you only need the index (or the key) and not the value. Use the _ (underscore) to ignore the value:
1
2
3
for index, _ := range numbers { // ignores the value
fmt.Println("Index:", index)
}
More info
range simplifies looping, providing a clean and efficient way to iterate through Go’s core data structures!
Loop Control: Break & Continue 🚀
Let’s explore how to fine-tune your loops with break and continue!
Breaking Free & Skipping Ahead
break: Think ofbreakas an emergency exit. It immediately terminates the loop’s execution, even if the loop condition is still true.1 2 3 4
for i in range(5): if i == 3: break # Exit the loop when i is 3 print(i) # output: 0, 1, 2
continue:continueis like a “fast forward” button. It skips the current iteration and jumps to the next one.1 2 3 4
for i in range(5): if i == 2: continue # Skip iteration when i is 2 print(i) # output: 0, 1, 3, 4
Labeled Break & Continue
For nested loops, you can use labels with
breakandcontinueto specify which loop you want to affect.1 2 3 4 5
outer_loop: for i in range(3): for j in range(3): if i == 1 and j == 1: break outer_loop # Exit the outer loop print(f"i={i}, j={j}")
Here is a flow chart explaining break and continue statement.
graph TD
A[Start Loop] --> B{Condition};
B -- True --> C{Code};
C --> D{Break Statement?};
D -- Yes --> E[Exit Loop];
D -- No --> F{Continue Statement?};
F -- Yes --> B;
F -- No --> G[Execute Rest of Loop];
G --> B;
B -- False --> E;
E --> H[End];
Practical Example: Searching in a 2D grid. If we find the target, we want to stop the entire search.
- Resource: Python
breakandcontinue
goto Statements and Labels in Go 🚀
goto in Go jumps execution to a labeled point within a function. Labels are markers in your code, like errHandler: before a block.
When goto Can Be Helpful
Error Handling: Quickly jump to a central error handling block.
1 2 3 4 5 6 7 8 9
func myFunc() error { // ... some code if err != nil { goto errHandler // Jump to error handling } // ... more code errHandler: return fmt.Errorf("error occurred: %w", err) }
Breaking Nested Loops: Exit multiple nested loops efficiently.
1 2 3 4 5 6 7 8
loop: for i := 0; i < 3; i++ { for j := 0; j < 3; j++ { if i*j > 5 { goto loop // Exit both loops } } }
Why Use Sparingly?
goto can make code harder to read and understand. Too many goto statements can create what is commonly referred to as “spaghetti code”. This makes debugging and maintaining the code much more difficult.
- It complicates control flow.
- It reduces code readability.
Best Practice: Prefer structured control flow (if/else, loops, functions). Use goto only when necessary and with extreme caution.
For more info you can check the official documentation on Go’s control flow.
Conclusion
Alright, folks, we’ve reached the end! 🥳 But the conversation doesn’t have to stop here! What are your takes on this? Did I miss anything important? 🤔 Drop a comment below and let’s chat! I value your feedback and suggestions. Happy commenting! ✍️