Go
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Functions and Methods
-
Section 4: Concurrency
-
Section 5: Packages and Tooling
-
Section 6: More Standard Library
-
Section 7: Building Services
-
Section 8: Advanced Go
-
Section 9: Go in the Cloud-Native Ecosystem
-
Section 10: Data Structures and Algorithms in Go
-
Section 11: Testing and Deployment
-
Section 12: Practical Projects
-
Section 13: More Standard Library Practice
-
Section 14: More Practice Projects
-
Section 15: Design Patterns in Go
-
Section 16: Interview Practice
-
Section 17: Package fmt In Depth
-
Section 18: Package strings and strconv
-
Section 19: Package os and io
-
Section 20: Package time
-
Section 21: Package sort and container
-
Section 22: Package encoding
-
Section 23: Package net/http In Depth
-
Section 24: Package context
-
Section 25: Package regexp and bytes
-
Section 26: Package errors In Depth
-
Section 27: Package crypto and hash
-
Section 28: Package flag and log
-
Section 29: Package sync In Depth
-
Section 30: More Practice Exercises
-
Section 31: Go Modules and Workspaces In Depth
-
Section 32: Generics Deep Dive (Go 1.18+)
-
Section 33: Testing Package In Depth
-
Section 34: More Interview and Whiteboard Practice
-
Section 35: Package math and unicode
-
Section 36: Package path and filepath
-
Section 37: Package database/sql
-
Section 38: Package text/template and html/template
-
Section 39: Package archive and compress
-
Section 40: Lower-Level net Package
-
Section 41: Package runtime and reflect
-
Section 42: Package embed and io/fs
-
Section 43: Go Assembly and CGO Basics
-
Section 44: Building CLIs and TUIs
-
Section 45: Go Performance Tuning
-
Section 46: More Real-World Projects
-
Section 47: Go in Production
-
Section 48: Go Design Patterns
-
Section 49: Go Interfaces Deep Dive
-
Section 50: Final Practice and Review
9: Control Flow: For Loops (Go's Only Loop)
Coming from other languages, the first thing you'll notice about Go is that it's obsessed with simplicity—sometimes to a point that feels aggressive. The best example of this is the loop. In Go, there is no while. There is no do-while. There is only for.
Now, don't let that panic you. The for keyword is a Swiss Army knife; it handles every looping scenario you'll ever encounter. To show you how, let's build a simple "Retry Mechanism." Imagine we're trying to connect to a flaky external API. We don't want to give up on the first failure, but we can't try forever or we'll hang the whole system.
Starting with the classic counter
Most of us start here. If you know C, Java, or JavaScript, this will look familiar. We want to try our connection exactly three times. I'll set up a simple loop with an initialization, a condition, and a post-statement.
package main
import "fmt"
func main() {
for i := 1; i <= 3; i++ {
fmt.Printf("Attempt %d: Connecting to API...\n", i)
// Imagine a network call happens here
}
fmt.Println("Done trying.")
}
This is the "standard" loop. It's predictable and clean. But in the real world, we usually don't want to run exactly three times regardless of the outcome. We want to stop as soon as the connection succeeds.
Simulating a "while" loop
Since Go doesn't have a while keyword, we just omit the initialization and the post-statement. If you only provide a condition, Go treats it exactly like a while loop in other languages. I'll rewrite this to keep trying as long as we haven't succeeded and haven't hit our limit.
attempts := 0
success := false
for attempts < 3 && !success {
attempts++
fmt.Printf("Attempt %d: Trying to connect...\n", attempts)
if attempts == 2 { // Let's pretend it works on the second try
success = true
fmt.Println("Connected!")
}
}
I personally prefer this style for retry logic. It reads more like a sentence: "For as long as attempts are less than three and we haven't succeeded, keep going."
The infinite loop and my classic mistake
Sometimes you don't know the exit condition upfront, or the exit logic is too complex for a single line. In those cases, you use the "forever" loop: just the word for with no condition at all. You then handle the exit using a break statement.
I actually tripped over this during a project a few months ago. I was writing a polling loop to check for a file on a disk. I wrote something like this:
// WARNING: This is the mistake I made
for {
fmt.Println("Checking for file...")
if fileExists() {
fmt.Println("Found it!")
// I forgot to put the 'break' here!
}
}
I ran the code, and it worked perfectly—until the file actually appeared. Then, my terminal turned into a blur of "Found it!" messages, printing thousands of times per second. I'd created an infinite loop because I forgot to tell Go to actually stop once the condition was met. It's a silly mistake, but it happens to the best of us when we're moving too fast.
Here is the corrected version. You always need a way out when using a bare for loop:
for {
fmt.Println("Checking for file...")
if fileExists() {
fmt.Println("Found it!")
break // This is the magic word that stops the loop
}
// I'd also add a sleep here so I don't melt my CPU
}
Choosing the right tool
So, which one should you use? If you have a fixed range, go with the three-component loop. If you're waiting for a specific state to change, the "while-style" loop is your friend. If you're building a background worker or a listener that runs until the program terminates (or hits a complex break condition), use the bare for.
📋 Practical Task
Exercise: Build a Limited-Attempt Password Validator
Create a program that simulates a login system. The user should have a maximum of 5 attempts to enter the correct password (you can hardcode the correct password as a string variable).
- Use a
forloop to track the number of attempts. - Inside the loop, simulate a password check.
- If the password is correct, print "Access Granted" and use
breakto exit the loop immediately. - If the password is incorrect, print "Incorrect password" and the number of attempts remaining.
- If the loop finishes all 5 iterations without a correct password, print "Account Locked: Too many failed attempts."
There are no comments for now.