Chapter 34: if else Statement
If … else statement — probably the most frequently used control structure in any programming language, including Go.
In Go, the if … else construction is extremely clean, very strict about style, and has one very powerful extra feature that almost no other language has in this form: the short variable declaration inside the if condition.
Let me explain everything like we’re sitting together with VS Code open, writing small programs, running them, and discussing why Go made each decision.
1. Basic Syntax Rules (very important to get right from day one)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 |
if condition { // statements } else if anotherCondition { // statements } else { // statements } |
Mandatory rules in Go (these are enforced by the compiler):
- No parentheses around the condition → correct: if age >= 18 { → wrong (but compiles): if (age >= 18) { — don’t do it, it’s non-idiomatic
- Braces {} are ALWAYS required — even for one single statement → correct: if x > 0 { return x } → forbidden: if x > 0 return x (this is one of the strongest style enforcements in Go)
- The condition must evaluate to a bool — no implicit conversion from int/float/pointer → if 1 { } → compile error → if ptr != nil { } → correct
2. Simple Examples — Copy-Paste & Run
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
package main import "fmt" func main() { temperature := 37 // 1. Basic if if temperature > 35 { fmt.Println("It's hot in Hyderabad today!") } // 2. if + else if temperature >= 40 { fmt.Println("Extreme heat warning ☀️🔥") } else { fmt.Println("Still hot, but manageable") } // 3. Full if – else if – else chain if temperature >= 45 { fmt.Println("Dangerous heat — stay indoors") } else if temperature >= 40 { fmt.Println("Very hot — hydrate a lot!") } else if temperature >= 35 { fmt.Println("Hot — avoid direct sun") } else if temperature >= 25 { fmt.Println("Warm and pleasant 🌤️") } else if temperature >= 15 { fmt.Println("Cool — nice weather") } else { fmt.Println("Cold — wear a jacket 🧥") } } |
3. The Most Powerful & Idiomatic Feature: if with Initialization
This is the thing that makes Go if feel very different (and better) than many other languages.
You can declare variables right inside the if condition — they exist only in the scope of that if / else if / else block.
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
// Pattern you will write hundreds of times file, err := os.Open("secrets.json") if err != nil { fmt.Println("Failed to open file:", err) return } // here 'file' is usable // 'err' is already gone — not visible anymore // Another very common style username := "webliance123" if length := len(username); length == 0 { fmt.Println("Username is required") } else if length < 3 { fmt.Println("Username too short") } else if length > 20 { fmt.Println("Username too long") } else { fmt.Println("Username accepted — length:", length) } // 'length' is NOT visible here — scoped only to the if/else chain |
Why is this pattern so loved in Go?
- Variables live only as long as needed
- No unnecessary variables polluting the outer scope
- Extremely clean error handling: if err != nil { return … }
- Reduces bugs from accidentally using stale/wrong variables
4. Combining Conditions with Logical & Comparison Operators
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
age := 19 hasLicense := false hasLearnersPermit := true isRaining := false if age >= 18 && hasLicense { fmt.Println("Can drive alone 🚗") } else if age >= 16 && hasLearnersPermit { fmt.Println("Can drive with adult supervisor") } else { fmt.Println("Cannot drive yet") } // Safe nil + value check (short-circuit evaluation) var highScore *int = nil if highScore != nil && *highScore >= 90 { fmt.Println("Excellent score!") } else { fmt.Println("No score or below 90") } |
Short-circuit evaluation — very important safety feature:
- && stops evaluating as soon as it finds false
- || stops as soon as it finds true
→ This is why ptr != nil && *ptr > 0 is safe
5. Idiomatic Go Patterns (What Real Code Looks Like)
Pattern 1: Guard clauses / early returns (very common in production code)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
func processPayment(payment *Payment) error { if payment == nil { return ErrNilPayment } if payment.Amount <= 0 { return ErrInvalidAmount } if !payment.IsValidMethod() { return ErrInvalidMethod } // happy path continues here return nil } |
Pattern 2: Input validation at the beginning
|
0 1 2 3 4 5 6 7 8 9 10 11 |
if email == "" { return fmt.Errorf("email is required") } if !strings.Contains(email, "@") { return fmt.Errorf("invalid email format") } |
Pattern 3: Checking ranges / bounds
|
0 1 2 3 4 5 6 7 8 |
if port < 1 || port > 65535 { return fmt.Errorf("invalid port: %d (must be 1–65535)", port) } |
6. Quick Practice – Try Writing These
- Create an if chain that classifies temperature in Hyderabad:
- < 10 → “Really cold ❄️”
- 10–20 → “Cool 🧥”
- 21–30 → “Pleasant 🌤️”
- 31–38 → “Hot ☀️”
-
38 → “Very hot 🔥”
- Write a safe check: if a slice is not niland has length > 0 and first element > 100, print “Strong start”
- Write a small function that returns early if any input parameter is invalid
Which style do you personally like more — long else if chains or many early returns?
Any part still unclear?
- Why Go forces braces {} even for one line?
- Why no ternary operator? (Go philosophy)
- How deep is too deep for if nesting?
- Or ready to move to switch statement next?
Keep writing small if blocks — they control almost every meaningful decision in your future programs.
You’re making excellent progress — keep asking! 💪🇮🇳🚀
