if and else
An if statement runs code only when a condition is true. Go's version has no parentheses, always needs braces, and can start with a short statement — a feature used constantly for checking errors. This lesson covers if, else if and else, the short-statement form, and the "return early" style that keeps Go code flat and readable.
if, else if, else
package main import "fmt" func main() { temperature := 14 if temperature > 25 { fmt.Println("Shorts weather") } else if temperature > 10 { fmt.Println("Bring a light jacket") } else { fmt.Println("Wrap up warm") } }
Bring a light jacket
Conditions are checked from top to bottom and only the first true branch runs. The condition must be a bool — if count { … } with an integer doesn't compile — and else must sit on the same line as the closing brace before it.
Combining conditions
package main import "fmt" func main() { age, hasID, isMember := 19, true, false if age >= 18 && hasID { fmt.Println("Entry allowed") } if isMember || age < 12 { fmt.Println("Free entry") } else { fmt.Println("Ticket required") } if !isMember { fmt.Println("Ask about membership") } }
Entry allowed Ticket required Ask about membership
if with a short statement
An if can begin with a short statement, separated from the condition by a semicolon. Variables declared there exist only inside the if and its else branches:
package main import ( "fmt" "strconv" ) func main() { input := "42" if n, err := strconv.Atoi(input); err != nil { fmt.Println("not a number:", err) } else if n%2 == 0 { fmt.Println(n, "is even") } else { fmt.Println(n, "is odd") } // n and err don't exist here }
42 is even
This keeps short-lived variables close to where they're used and out of the rest of the function. You'll see if err := doSomething(); err != nil { … } in almost every Go program.
Return early
Go code favours handling problems first and returning, so the main logic isn't buried in nested else blocks. Compare these two versions of the same function:
package main import ( "errors" "fmt" ) // Nested: the happy path drifts to the right. func withdrawNested(balance, amount int) (int, error) { if amount > 0 { if amount <= balance { return balance - amount, nil } else { return balance, errors.New("insufficient funds") } } else { return balance, errors.New("amount must be positive") } } // Early returns: each problem is handled and dismissed, then the real work. func withdraw(balance, amount int) (int, error) { if amount <= 0 { return balance, errors.New("amount must be positive") } if amount > balance { return balance, errors.New("insufficient funds") } return balance - amount, nil } func main() { fmt.Println(withdrawNested(100, 30)) fmt.Println(withdraw(100, 30)) fmt.Println(withdraw(100, 300)) fmt.Println(withdraw(100, -5)) }
70 <nil> 70 <nil> 100 insufficient funds 100 amount must be positive
The second version is the idiomatic one: the main path runs straight down the left edge. Linters even flag an else after a branch that ends in return as unnecessary.
No ternary operator
Go has no cond ? a : b. Assign a default and override it, or use a small if/else:
package main import "fmt" func main() { items := 1 label := "items" if items == 1 { label = "item" } fmt.Println(items, label) }
1 item
It takes a couple more lines, but every condition in Go reads the same way.
Try it yourself
Turn a numeric score into a letter grade. Add an "A+" for 97 and above.
95 A 83 B 71 C 64 D 40 F
switch.