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.
Basic match
Section titled “Basic match”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:
WednesdayThe _ 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.”
Matching multiple values at once
Section titled “Matching multiple values at once”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"), }}Matching a range
Section titled “Matching a range”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"), }}match as an expression
Section titled “match as an expression”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}");}Matching text and characters
Section titled “Matching text and characters”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 consonantHi, crab!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
Stringneeds.as_str(). Text written in quotes, like"Ferris", is a&str. If youmatchaStringdirectly against it, Rust stops witherror[E0308]: mismatched types ... expected String, found &str. Calling.as_str()gives you a&strview of theStringthat 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().
match vs if/else
Section titled “match vs if/else”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.
Practice
Section titled “Practice”1. Days in a month
Section titled “1. Days in a month”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 days2. HTTP status codes
Section titled “2. HTTP status codes”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 errormatchcompares 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
&strtext andcharvalues too; use.as_str()to match aString. match, likeif, can be used as an expression to produce a value.
Quick check
Section titled “Quick check”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
Read more
Section titled “Read more”- The match Control Flow Construct — The Rust Book: the official chapter, which also shows
matchon enums andOption. - match — Rust by Example: a compact runnable example with values,
|, ranges and_. - Range patterns — The Rust Reference: exactly which types and range forms you can use in a pattern.
- Match expressions — The Rust Reference: the precise rules for arms, guards and how a
matchproduces its value.