Skip to content

Rust Option

Rust doesn’t have null. If a value might be missing, that’s expressed directly in the type using Option. It feels like extra ceremony at first, but it closes off an entire category of bugs — the “null reference” that’s caused countless crashes in other languages.

Option is an enum with two variants:

enum Option<T> {
Some(T), // a value is present
None, // no value
}

You’ve actually already seen this — .get() on a vector and .get() on a HashMap both return an Option.

fn main() {
let has_value: Option<i32> = Some(5);
let no_value: Option<i32> = None;
println!("{:?}", has_value);
println!("{:?}", no_value);
}

Output:

Some(5)
None
▶ Try it Yourself

The safe way to get the value out is match — Rust forces you to handle both cases, so you can’t accidentally forget the “missing” case:

fn main() {
let age: Option<i32> = Some(30);
match age {
Some(value) => println!("Age is {value}"),
None => println!("No age given"),
}
}
▶ Try it Yourself
fn find_user(id: u32) -> Option<&'static str> {
if id == 1 {
Some("Alice")
} else {
None
}
}
fn main() {
match find_user(1) {
Some(name) => println!("Found: {name}"),
None => println!("User not found"),
}
match find_user(99) {
Some(name) => println!("Found: {name}"),
None => println!("User not found"),
}
}

Output:

Found: Alice
User not found
▶ Try it Yourself

Instead of returning null or throwing when a user isn’t found, the function’s return type itself tells every caller “this might not find anything” — and the compiler won’t let them ignore that possibility.

For simple cases, a full match can feel like overkill. A couple of shortcuts:

fn main() {
let age: Option<i32> = None;
let value = age.unwrap_or(0); // fall back to 0 if there's no value
println!("{value}");
}
▶ Try it Yourself

There’s also .unwrap(), which gives you the value directly — but panics (crashes) if it’s None:

let age: Option<i32> = Some(30);
let value = age.unwrap(); // fine here, since age is Some
  • Option<T> represents a value that might or might not be present — Rust has no null.
  • Some(value) holds something; None means nothing is there.
  • match is the safe way to handle both cases; the compiler won’t let you forget one.
  • .unwrap_or(default) gives you a fallback; .unwrap() panics if the value is None — use it sparingly.

Quick check

1. What does Rust use instead of null for a value that might be missing?

2. What happens when you call .unwrap() on a None value?

3. What does age.unwrap_or(0) do when age is None?

4. Why is match considered the safe way to get a value out of an Option?

5. Which methods mentioned on this page already return an Option?

Score: 0 / 5