Skip to content

Rust Match

match compares a value against a list of patterns and runs the code for whichever one fits. Think of it as a more powerful version of a switch statement, if you’ve used one before — and if you haven’t, it’s still one of the more useful patterns to learn early.

fn main() {
let day = 3;
match day {
1 => println!("Monday"),
2 => println!("Tuesday"),
3 => println!("Wednesday"),
4 => println!("Thursday"),
5 => println!("Friday"),
_ => println!("Weekend"),
}
}

Output:

Wednesday
▶ Try it Yourself

The _ is a catch-all — it matches anything not listed above it. match requires every possible value to be handled, so _ is usually there to cover “everything else.”

You can group several values into one arm using |:

fn main() {
let day = 6;
match day {
1 | 2 | 3 | 4 | 5 => println!("Weekday"),
6 | 7 => println!("Weekend"),
_ => println!("Not a valid day"),
}
}
▶ Try it Yourself

For numbers, you can match a whole range with ..=:

fn main() {
let score = 85;
match score {
90..=100 => println!("A"),
75..=89 => println!("B"),
60..=74 => println!("C"),
_ => println!("F"),
}
}
▶ Try it Yourself

Just like if, match can produce a value:

fn main() {
let day = 6;
let kind = match day {
1 | 2 | 3 | 4 | 5 => "weekday",
6 | 7 => "weekend",
_ => "unknown",
};
println!("{kind}");
}
▶ Try it Yourself

match isn’t only for numbers. It works on string slices (&str) and on characters too, and character ranges like 'a'..='z' work just like number ranges:

fn main() {
let command = "stop";
match command {
"start" => println!("Starting..."),
"stop" | "quit" => println!("Stopping."),
_ => println!("Unknown command: {command}"),
}
let letter = 'k';
let kind = match letter {
'a' | 'e' | 'i' | 'o' | 'u' => "vowel",
'a'..='z' => "consonant",
'0'..='9' => "digit",
_ => "something else",
};
println!("'{letter}' is a {kind}");
let name = String::from("Ferris");
match name.as_str() {
"Ferris" => println!("Hi, crab!"),
_ => println!("Hi, {name}!"),
}
}

Output:

Stopping.
'k' is a consonant
Hi, crab!
▶ Try it Yourself

Two things are worth noticing here:

  • Order matters. 'a' is also inside 'a'..='z', but the vowel arm comes first, so vowels never reach the consonant arm. Rust always picks the first arm that fits.
  • A String needs .as_str(). Text written in quotes, like "Ferris", is a &str. If you match a String directly against it, Rust stops with error[E0308]: mismatched types ... expected String, found &str. Calling .as_str() gives you a &str view of the String that the patterns can compare against. (See the Strings page for the difference between the two.)

Matching is case-sensitive: "Stop" would not match "stop". If the text comes from a user, a common trick is to match on input.to_lowercase().as_str().

Either works for simple true/false checks, but match starts to win once you have more than two or three possibilities — it reads better than a long chain of else if, and the compiler checks you’ve covered every case. if/else is still the right tool for a single yes/no condition.

Store a month number (2). Use match as an expression to work out how many days it has (ignore leap years), then print Month 2 has 28 days. Hint: months 1, 3, 5, 7, 8, 10 and 12 have 31 days; group them into one arm with |.

Show solution
fn main() {
let month = 2;
let days = match month {
1 | 3 | 5 | 7 | 8 | 10 | 12 => 31,
4 | 6 | 9 | 11 => 30,
2 => 28,
_ => 0, // not a real month
};
println!("Month {month} has {days} days");
}

Output:

Month 2 has 28 days
▶ Try it Yourself

Web servers answer with a number. Turn a code into a short meaning: 200 is "OK", 404 is "Not Found", any other 400–499 is "Client error", 500–599 is "Server error", and anything else is "Unknown". Try it with 503. Hint: put the exact 404 arm above the 400..=499 range, or it will never be reached.

Show solution
fn main() {
let code = 503;
let meaning = match code {
200 => "OK",
404 => "Not Found", // must come before the 400..=499 range
400..=499 => "Client error",
500..=599 => "Server error",
_ => "Unknown",
};
println!("{code}: {meaning}");
}

Output:

503: Server error
▶ Try it Yourself
  • match compares a value against patterns and runs the matching arm.
  • Every possible value must be handled — use _ as a catch-all.
  • Combine values with |, or match a range with ..=.
  • You can match &str text and char values too; use .as_str() to match a String.
  • match, like if, can be used as an expression to produce a value.

Quick check

1. What does the _ pattern do in a match expression?

2. What happens if a match expression doesn't handle every possible value and has no _ arm?

3. How do you match several values in one arm, like 1, 2, or 3?

Score: 0 / 3