# Conditional Statements

Course: [Go](https://www.devtutorials.ai/learn/go) · Section: Control Flow
Source: https://www.devtutorials.ai/learn/go/control-flow/conditional-statements

> Make choices in Go with if, if with a short statement, else, else if chains, nested if, switch, multiple cases, fallthrough and the expressionless switch.

## What Are Conditional Statements?

**Conditional statement** = code that runs only when a condition is true.

**Condition** = a question with a `true` or `false` answer, like `marks >= 35`.

With conditions, your program can make choices:

- if marks are 35 or more, print "Pass"
- otherwise, print "Try again"

**Simple lesson:** conditional statements let a program choose what to do.

### A Real-World Example

The school gate has a guard.

- If you have an ID card, you go in.
- If not, but you have a gate pass, you also go in.
- Otherwise, you wait at the office.

The guard checks one question at a time, in order.
He stops at the first "yes".

Now the mapping:

- **Each question** = a condition.
- **What the guard does** = the code that runs.
- **Stopping at the first yes** = how `if` and `else if` work.

Go has two tools for choices:

- `if`, with `else if` and `else`
- `switch`, for choosing between many values

Both use the comparison and logical operators from **Operators**.

## What You Will Learn

In this lesson, you will learn:

1. How to write an `if` statement, with an initialization part.
2. How to choose between paths with `else` and `else if`.
3. How to put one `if` inside another.
4. How `switch` picks one case, and what `fallthrough` does.
5. How to keep conditions easy to read.

## The if Statement

### Basic Syntax

```go
if condition {
	// runs only when condition is true
}
```

- No parentheses `( )` around the condition.
- The braces `{ }` are always needed, even for one line.
- `{` must be on the same line as `if`.

```go runnable title="Pass mark check"
package main

import "fmt"

func main() {
	marks := 72
	if marks >= 35 {
		fmt.Println("Pass")
	}
	fmt.Println("Report card printed")
}
```

```text
Pass
Report card printed
```

- `marks >= 35` is true, so `"Pass"` prints.
- The last line is outside the `if`, so it always prints.

Change `marks` to `20` and run again.
Only the last line prints.

### The Condition Must Be a bool

```go runnable expect-error title="A number is not a condition"
package main

import "fmt"

func main() {
	count := 3
	if count {
		fmt.Println("Students present")
	}
}
```

- Some languages treat `3` as true. Go does not.
- Go stops with an error like `non-boolean condition in if statement`.
- Fix: ask a real question, like `if count > 0`.

### Initialization Statement

An `if` can start with a short statement, then a `;`, then the condition.

```go
if value := work(); value > 10 {
	// value can be used here
}
// value does not exist here
```

- The statement runs first, then the condition is checked.
- Variables made there live **only inside** the `if`.
- It is often used with functions that return an error.

```go runnable title="Read a number and check it at once"
package main

import (
	"fmt"
	"strconv"
)

func main() {
	if age, err := strconv.Atoi("13"); err == nil {
		fmt.Println("Age next year:", age+1)
	}
}
```

```text
Age next year: 14
```

- `age` and `err` are made, then `err == nil` is checked.
- The text was a valid number, so there is no error.

**Simple lesson:** `if` runs its block only when the condition is true, and the condition must be a `bool`.

## if else Statement

### Alternative Execution Paths

**else** = the block that runs when the condition is false.

```go runnable title="Pass or try again"
package main

import "fmt"

func main() {
	marks := 28
	if marks >= 35 {
		fmt.Println("Pass")
	} else {
		fmt.Println("Try again")
	}
}
```

```text
Try again
```

- Exactly **one** of the two blocks runs.
- `else` must be on the same line as the `}` before it: `} else {`.

### else if Chains

For more than two paths, add `else if`.

Move the slider and watch which branch runs.

Try these marks:

- **95:** the first check is true, so Go stops there.
- **80:** the first check is false, the second is true.
- **20:** every check is false, so `else` runs.

```go runnable title="Grades with else if"
package main

import "fmt"

func main() {
	marks := 82
	if marks >= 90 {
		fmt.Println("Grade A")
	} else if marks >= 75 {
		fmt.Println("Grade B")
	} else if marks >= 50 {
		fmt.Println("Grade C")
	} else {
		fmt.Println("Needs practice")
	}
}
```

```text
Grade B
```

- Go checks from the top, one condition at a time.
- It runs the **first** true block and skips all the rest.
- So put the strictest check (`>= 90`) first.

### Nested if

**Nested if** = an `if` inside another `if`.

Press **Play** and follow the path.

- The inner `if` is checked only when the outer one is true.
- Deep nesting is hard to read. Two levels is usually enough.

Go has no `? :` (ternary) operator, unlike C, Java or JavaScript.

Write a short `if` and `else` instead. Go keeps one clear way to make a choice.

**Simple lesson:** `else` gives a second path, `else if` adds more paths, and Go takes the first true one.

## The switch Statement

**switch** = compare one value against many cases, and run the matching one.

It is a neat way to write a long `else if` chain.

### Basic Switch

```go runnable title="Day of the timetable"
package main

import "fmt"

func main() {
	day := "Wednesday"
	switch day {
	case "Monday":
		fmt.Println("Maths first period")
	case "Wednesday":
		fmt.Println("Library period")
	case "Friday":
		fmt.Println("Sports period")
	default:
		fmt.Println("Regular classes")
	}
}
```

```text
Library period
```

- Go compares `day` with each `case`, from top to bottom.
- It runs the **first** match and then leaves the switch.
- You do **not** need `break`, unlike C or Java.
- `default` runs when no case matches. It is optional.

### Multiple Cases

One case can list many values, separated by commas.

Pick a day and watch which case runs.

Look at two things:

- **Sat and Sun** share one case.
- **Fri with fallthrough** runs its case **and** the next one.

```go runnable title="Weekend or weekday?"
package main

import "fmt"

func main() {
	day := "Sunday"
	switch day {
	case "Saturday", "Sunday":
		fmt.Println("Holiday!")
	default:
		fmt.Println("School day")
	}
}
```

```text
Holiday!
```

### Fallthrough

**fallthrough** = also run the **next** case's code, without checking it.

```go runnable title="fallthrough runs the next case too"
package main

import "fmt"

func main() {
	level := 2
	switch level {
	case 3:
		fmt.Println("Gold badge")
		fallthrough
	case 2:
		fmt.Println("Silver badge")
		fallthrough
	case 1:
		fmt.Println("Bronze badge")
	}
}
```

```text
Silver badge
Bronze badge
```

- `level` is 2, so the `case 2` block runs.
- `fallthrough` moves into `case 1` without checking it.
- `fallthrough` must be the last line of a case.
- It is rare in real Go code. Use it only when it makes the meaning clear.

### Expressionless Switch

**Expressionless switch** = a `switch` with no value after it. Each `case` is a full condition.

It is a tidy way to write an `else if` chain.

```go runnable title="Grades with an expressionless switch"
package main

import "fmt"

func main() {
	marks := 67
	switch {
	case marks >= 90:
		fmt.Println("Grade A")
	case marks >= 75:
		fmt.Println("Grade B")
	case marks >= 50:
		fmt.Println("Grade C")
	default:
		fmt.Println("Needs practice")
	}
}
```

```text
Grade C
```

- `switch {` is the same as `switch true {`.
- Go runs the first case whose condition is true.

### switch with an Initialization Statement

Like `if`, a `switch` can start with a short statement.

```go runnable title="switch with a short statement"
package main

import "fmt"

func main() {
	switch total := 45 + 38; {
	case total >= 80:
		fmt.Println("Team qualifies:", total)
	default:
		fmt.Println("Team does not qualify:", total)
	}
}
```

```text
Team qualifies: 83
```

**Easy way to remember**

- Go's `switch` stops after one case. No `break` needed.
- `fallthrough` is the only way to run the next case too.
- No value after `switch` = each case is its own condition.

**Simple lesson:** `switch` runs the first matching case and stops, unless that case ends with `fallthrough`.

## Conditional Best Practices

### Readability

- **Return early.** Handle the bad case first, then the normal case without `else`.
- **Name your conditions.** `isAdult := age >= 18` reads better than a long check.
- **Use `switch`** when one value is compared with many cases.
- **Avoid deep nesting.** More than two levels is hard to follow.

### Decision Trees

**Decision tree** = a drawing of every question and every path.

Before writing a long chain:

- draw the questions as boxes
- draw a "yes" and a "no" arrow from each box
- check that every path ends in an answer
- then write the code in the same order

```go runnable title="A fee concession decision tree"
package main

import "fmt"

func main() {
	marks := 92
	siblings := 1

	isTopper := marks >= 90
	hasSibling := siblings > 0

	switch {
	case isTopper && hasSibling:
		fmt.Println("Concession: 50%")
	case isTopper || hasSibling:
		fmt.Println("Concession: 25%")
	default:
		fmt.Println("Concession: none")
	}
}
```

```text
Concession: 50%
```

- The two named conditions make each case easy to read.
- The order matters: the `&&` case must come before the `||` case.

**Simple lesson:** name your conditions, return early, and keep the choices flat and in a clear order.

## TL;DR

1. **if** = `if condition { }`. No parentheses, braces always needed.
   - The condition must be a `bool`.
   - **Initialization** = `if x := f(); x > 0 { }`. `x` lives only inside.
2. **else** = the block when the condition is false. **else if** = more paths.
   - Go runs the first true block only.
3. **Nested if** = an `if` inside an `if`. Keep it shallow.
4. **switch** = match one value against cases.
   - No `break` needed. `default` = no match.
   - **Multiple cases** = `case "Sat", "Sun":`
   - **fallthrough** = also run the next case.
   - **Expressionless switch** = `switch { case x > 5: ... }`
5. **Best practice** = name conditions, return early, avoid deep nesting.

## Common mistakes

| Mistake | Wrong idea | Correct idea | What goes wrong |
|---|---|---|---|
| `if (marks >= 35)` with no braces after | Like C, braces are optional | Braces are always needed | A syntax error. |
| `if count {` | A number can be a condition | The condition must be a `bool` | `non-boolean condition in if statement` |
| `}` then `else` on the next line | `else` can go anywhere | Write `} else {` on one line | A syntax error. |
| `>= 50` checked before `>= 90` | Order does not matter | The first true case wins | Every topper gets Grade C. |
| Adding `break` to each case | Cases fall through by default | Go stops after one case | Extra noise, no change. |
| Expecting `fallthrough` to check the next case | It tests the next condition | It runs the next case without checking | Wrong output. |
| Using `x` after `if x := ...; { }` | It stays alive | It lives only inside the `if` | `undefined: x` |

## Check Yourself

## Exercises

## What to Remember

- `if` runs a block only when its condition is true. The condition must be a `bool`.
- No parentheses, but braces are always needed, and `} else {` stays on one line.
- `else if` chains run the **first** true block. Put the strictest check first.
- `if x := f(); cond { }` makes `x` live only inside the `if`.
- `switch` runs one matching case and stops. `fallthrough` runs the next one too.
- Keep choices flat: name conditions and return early.

Next: **Loops**. You will learn how to repeat work with `for` and `range`.
