M Logo
๐Ÿ“ Rust for Beginners ยท Part 13 of 22

Rust Option Explained: Some, None, if let, unwrap_or โ€“ No null in Rust

November 10, 2026

Welcome to episode 13 of Rust for Beginners, a series for complete beginners (no programming experience needed). In the last video, we learned about enums and match. Today, we'll meet the most used enum of all: Option. It's how Rust handles a missing value, without null. Every code block below is the exact code from the video, ready to copy.

1. New project

Let's create a new project called options, and open it in VS Code.

bash
cargo new options
cd options

2. Null problem

In many languages, any value can secretly be null, and using it crashes the program. Its inventor called null his billion-dollar mistake.

3. Option

Rust has no null. Instead, a value that might be missing is an Option. It's an enum with two variants: Some, holding a value, or None.

4. Example

Here, some number is Some five, and no number is None. Both have the type Option of i thirty-two.

src/main.rs:

rust
fn main() {
    let some_number: Option<i32> = Some(5);
    let no_number: Option<i32> = None;

    let total = some_number + 1;
}

Error:

text
error[E0369]: cannot add `{integer}` to `Option<i32>`
 --> src/main.rs:5:29
  |
5 |     let total = some_number + 1;
  |                 ----------- ^ - {integer}
  |                 |
  |                 Option<i32>
  |
note: `Option<i32>` does not implement `Add<{integer}>`
 --> /rustc/58cf8f9c35b355199727627d07ae34a4e2846d67/library/core/src/option.rs:598:0
  |
  = note: `Option<i32>` is defined in another crate

5. Error

Can we just add one to it?

bash
cargo run

6. Why

No. An Option of i thirty-two is not an i thirty-two. Rust makes us check for None first, so we can never forget.

7. Return Option

Functions return Option when there might be no answer. divide returns None when we try to divide by zero.

rust
fn divide(a: f64, b: f64) -> Option<f64> {
    if b == 0.0 {
        None
    } else {
        Some(a / b)
    }
}

fn main() {
    for b in [4.0, 0.0] {
        match divide(10.0, b) {
            Some(result) => println!("10 / {b} = {result}"),
            None => println!("10 / {b}: can't divide by zero!"),
        }
    }
}

Output: 10 / 4 = 2.5 / 10 / 0: can't divide by zero!

8. match

To use the result, we match on it. In the Some arm, we get the value out. In the None arm, we handle the missing case.

9. Run B

Let's run it. Ten divided by four is two point five, and dividing by zero is handled, without a crash.

bash
cargo run

10. get

Many standard functions return Option. get on an array gives Some item if the index exists, or None if it doesn't.

rust
fn main() {
    let names = ["Ann", "Bob", "Cat"];

    if let Some(name) = names.get(1) {
        println!("Found: {name}");
    }

    let missing = names.get(10);
    println!("Index 10: {missing:?}");
    println!("Or default: {}", missing.unwrap_or(&"nobody"));

    println!("{}", missing.unwrap());
}

Output (verified in the VM; the thread number changes every run):

text
Found: Bob
Index 10: None
Or default: nobody

thread 'main' (3496) panicked at src/main.rs:12:28:
called `Option::unwrap()` on a `None` value
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

11. if let

When we only care about the Some case, if let is shorter than match.

12. unwrap_or

unwrap or gives us the value, or a default if it's None.

13. unwrap

And unwrap takes the value out, but if it's None, the program panics. Let's see.

14. Run C

Found Bob, index ten is None, the default is nobody, and then the unwrap panics. So use unwrap only when you're sure there's a value.

bash
cargo run

Recap

To recap: Rust has no null. A maybe-missing value is an Option: Some or None. Use match or if let to get the value, unwrap or for a default, and unwrap only when you're sure.

ยฉ 2026 All Rights Reserved By Mahmudul Alam