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
8: Control Flow: If/Else
Wait, do I really not need parentheses around the condition?
If you're coming from Java, C#, or JavaScript, your fingers are probably itching to type if (x > 10). In Go, we drop the parentheses. You just write if x > 10 { ... }. Trust me, once you get used to it, the code feels much cleaner and less cluttered.
One thing you cannot skip, however, are the curly braces. Even if your if-block is only one line long, Go requires the braces. I've seen plenty of beginners try to omit them, but the compiler will shut you down immediately. It's a design choice to keep the code consistent and avoid those classic "dangling else" bugs that haunt other languages.
// This is the Go way
if userAge >= 18 {
fmt.Println("Access granted")
}
How do I handle multiple different conditions?
It works exactly how you'd expect: you use else if and else. The key is that Go evaluates these in order. As soon as it finds a condition that is true, it executes that block and skips the rest of the chain.
Let's say we're building a simple logic gate for a server's health check. We want to categorize the status based on response time:
responseTime := 450 // in milliseconds
if responseTime < 200 {
fmt.Println("System is Healthy")
} else if responseTime < 500 {
fmt.Println("System is Slow")
} else {
fmt.Println("System is Critical")
}
I usually suggest keeping these chains relatively short. If you find yourself writing ten else if blocks in a row, you might want to reconsider using a switch statement instead (which we'll hit in a later lesson).
What is that weird semicolon doing inside my if statement?
You'll often see Go code that looks like this: if err := doSomething(); err != nil { ... }. This is one of my favorite idiomatic features of the language. It's called an "if with a short statement."
Essentially, Go lets you initialize a variable and check its value in one single line. The magic part? The variable you create (in this case, err) is only scoped to the if/else blocks. It doesn't leak out into the rest of your function.
This is incredibly useful for keeping your namespace clean. Here is a practical example where we check if a user is "Active" before proceeding:
// Imagine checkStatus() returns a boolean and an error
if active, err := checkStatus(userID); err != nil {
fmt.Println("Error checking status:", err)
} else if !active {
fmt.Println("User account is deactivated")
} else {
fmt.Println("User is active! Proceeding...")
}
// 'active' and 'err' are not accessible here; they died with the if block.
I use this pattern constantly, especially when handling errors. It keeps the "setup" logic right next to the "check" logic, which makes the code much easier to read during a code review.
📋 Practical Task
Exercise: Building a Tiered Subscription Access Checker
You are tasked with writing a piece of logic for a SaaS platform. The platform has three tiers: "free", "pro", and "enterprise". You need to determine if a user can access a specific "Advanced Analytics" feature based on their tier.
Requirements:
- Create a variable
userTier(string). - Create a variable
isAccountSuspended(boolean). - Use an
if/else if/elsestructure to implement the following logic:- If
isAccountSuspendedis true, print "Access Denied: Account Suspended". - If the tier is
"enterprise"or"pro", print "Access Granted". - If the tier is
"free", print "Access Denied: Please upgrade to Pro". - For any other unexpected tier value, print "Access Denied: Invalid Tier".
- If
Bonus: Try to implement the isAccountSuspended check using the "short statement" syntax by initializing a dummy variable within the if line.
There are no comments for now.