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

GO
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")
	}
}
Output
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

GO
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")
	}
}
Output
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:

GO
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
}
Output
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:

GO
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))
}
Output
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:

GO
package main

import "fmt"

func main() {
	items := 1

	label := "items"
	if items == 1 {
		label = "item"
	}
	fmt.Println(items, label)
}
Output
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.

Try it yourself · main.go
Edit the code, copy it into main.go in a new folder and run it with go run main.go (Go 1.27 or later). How to install Go
Output
95 A
83 B
71 C
64 D
40 F
Next: choosing between many cases with switch.