Rust
Updated: May 22, 2026Categories: Languages
Printed from:
Rust Cheatsheet
Language Overview
Rust is a systems programming language focused on:
- Memory safety without garbage collection
- Concurrency without data races
- Zero-cost abstractions
- Performance comparable to C/C++
- Safe and predictable memory management
Basic Syntax
Rust
1234567891011// Single-line comment
/* Multi-line
comment */
// Main function - entry point of Rust program
fn main() {
println!("Hello, Rust!");
}
// Semicolons are required to end statements
let x = 5; // Variable declaration
Data Types
Primitive Types
Rust
12345678910111213141516171819202122// Integers
let integer_8: i8 = -128; // Signed 8-bit integer
let unsigned_16: u16 = 65535; // Unsigned 16-bit integer
let integer_64: i64 = 1_000_000; // Underscores for readability
// Floating point
let float_32: f32 = 3.14;
let float_64: f64 = 2.71828;
// Boolean
let is_true: bool = true;
let is_false: bool = false;
// Character (single Unicode scalar value)
let character: char = 'A';
// Tuple
let tuple: (i32, f64, char) = (500, 6.4, '😊');
// Unit type (similar to void in other languages)
let unit: () = ();
Collection Types
Rust
1234567891011121314151617// Vector (dynamic array)
let mut vec: Vec<i32> = vec![1, 2, 3];
vec.push(4);
// Array (fixed-size)
let array: [i32; 5] = [1, 2, 3, 4, 5];
// HashMap
use std::collections::HashMap;
let mut map = HashMap::new();
map.insert("key", "value");
// HashSet
use std::collections::HashSet;
let mut set = HashSet::new();
set.insert(1);
Variables and Constants
Rust
123456789101112131415161718192021222324// Immutable variable (default)
let x = 5;
// x = 6; // This would cause a compile-time error
// Mutable variable
let mut y = 10;
y = 15; // This is allowed
// Constants (always immutable, must be type annotated)
const MAX_POINTS: u32 = 100_000;
// Shadowing (creating a new variable with same name)
let x = 5;
let x = x + 1; // x is now 6
let x = "six"; // x can change type
// let-else for early return on pattern mismatch (stable since 1.65)
fn get_count(s: &str) -> i32 {
let Ok(n) = s.parse::<i32>() else {
return 0;
};
n
}
Operators
Arithmetic Operators
Rust
123456let sum = 5 + 10;
let difference = 95.5 - 4.3;
let product = 4 * 30;
let quotient = 56.7 / 32.2;
let remainder = 43 % 5;
Comparison Operators
Rust
1234567let a = 5;
let b = 10;
let is_equal = a == b;
let is_not_equal = a != b;
let is_greater = a > b;
let is_less_or_equal = a <= b;
Logical Operators
Rust
123456let x = true;
let y = false;
let and_result = x && y; // Logical AND
let or_result = x || y; // Logical OR
let not_result = !x; // Logical NOT
Control Structures
Conditional Statements
Rust
1234567891011121314151617181920212223// If-Else
let number = 7;
if number < 5 {
println!("Less than 5");
} else if number == 5 {
println!("Equal to 5");
} else {
println!("Greater than 5");
}
// Match expression
let result = match number {
1 => "one",
2 => "two",
n if n > 10 => "big", // match guard
_ => "other",
};
// if let / while let for single-pattern matching
if let Some(value) = Some(42) {
println!("Got {value}");
}
Loops
Rust
1234567891011121314151617181920212223242526272829303132333435363738// Infinite loop
loop {
// do something
break; // Exit loop
}
// loop can return a value
let result = loop {
break 42;
};
// While loop
let mut counter = 0;
while counter < 5 {
println!("{counter}");
counter += 1;
}
// For loop (range)
for number in 1..5 {
println!("{number}");
}
// For loop with iterator (explicit .iter() rarely needed since arrays implement IntoIterator)
let array = [10, 20, 30, 40, 50];
for element in array {
println!("{element}");
}
// Labeled loops for breaking outer scopes
'outer: for i in 0..10 {
for j in 0..10 {
if i * j > 20 {
break 'outer;
}
}
}
Functions
Rust
123456789101112131415161718192021222324252627282930313233// Basic function
fn add(a: i32, b: i32) -> i32 {
a + b // Implicit return
}
// Function returning a Result
fn divide(a: f64, b: f64) -> Result<f64, String> {
if b == 0.0 {
Err("Division by zero".to_string())
} else {
Ok(a / b)
}
}
// Closure (captures environment)
let multiply = |a: i32, b: i32| a * b;
// Generic function with trait bounds
fn largest<T: PartialOrd>(list: &[T]) -> &T {
let mut largest = &list[0];
for item in list {
if item > largest {
largest = item;
}
}
largest
}
// `impl Trait` in argument and return position
fn make_adder(x: i32) -> impl Fn(i32) -> i32 {
move |y| x + y
}
Error Handling
Rust
12345678910111213141516171819202122232425262728293031// Result type for recoverable errors
fn divide(a: f64, b: f64) -> Result<f64, String> {
if b == 0.0 {
Err("Division by zero".to_string())
} else {
Ok(a / b)
}
}
// Option type for nullable values
fn find_user(id: u32) -> Option<String> {
if id == 1 {
Some("User Found".to_string())
} else {
None
}
}
// `?` operator propagates errors
fn parse_and_double(s: &str) -> Result<i32, std::num::ParseIntError> {
let n: i32 = s.parse()?;
Ok(n * 2)
}
// Unwrapping Results and Options
let result = divide(10.0, 2.0).unwrap(); // Panics if Err
let safe_result = divide(10.0, 2.0).unwrap_or(0.0); // Default value
let lazy_result = divide(10.0, 2.0).unwrap_or_else(|_| 0.0);
// Use `anyhow` for application errors and `thiserror` for library errors
Object-Oriented Programming
Structs (Similar to Classes)
Rust
1234567891011121314151617181920212223242526272829303132333435363738394041424344// Basic struct
struct Rectangle {
width: u32,
height: u32,
}
// Struct with methods
impl Rectangle {
// Associated function (constructor-like)
fn new(width: u32, height: u32) -> Self {
Self { width, height }
}
// Method
fn area(&self) -> u32 {
self.width * self.height
}
}
// Creating and using struct
let rect = Rectangle::new(10, 20);
println!("Area: {}", rect.area());
// Tuple structs and unit structs
struct Point(i32, i32);
struct Marker;
// Enums with data and methods
enum Shape {
Circle(f64),
Square(f64),
Rectangle { w: f64, h: f64 },
}
impl Shape {
fn area(&self) -> f64 {
match self {
Shape::Circle(r) => std::f64::consts::PI * r * r,
Shape::Square(s) => s * s,
Shape::Rectangle { w, h } => w * h,
}
}
}
Traits (Similar to Interfaces)
Rust
1234567891011121314151617181920212223242526272829trait Drawable {
fn draw(&self);
// Default method implementation
fn describe(&self) {
println!("A drawable shape");
}
}
struct Circle {
radius: f64,
}
impl Drawable for Circle {
fn draw(&self) {
println!("Drawing a circle of radius {}", self.radius);
}
}
// Derive common traits automatically
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
struct Point {
x: i32,
y: i32,
}
// Trait objects for dynamic dispatch
let shapes: Vec<Box<dyn Drawable>> = vec![Box::new(Circle { radius: 1.0 })];
Memory Management
Ownership and Borrowing
Rust
12345678910111213141516171819202122fn main() {
let s1 = String::from("hello");
let s2 = s1; // s1 is moved, no longer valid
// println!("{}", s1); // Compile error
// Immutable borrow
let s3 = String::from("world");
let len = calculate_length(&s3);
// Mutable borrow (only one allowed at a time)
let mut s4 = String::from("hello");
append_world(&mut s4);
}
fn calculate_length(s: &String) -> usize {
s.len()
}
fn append_world(s: &mut String) {
s.push_str(" world");
}
Lifetimes
Rust
12345678910// Explicit lifetime annotation
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() { x } else { y }
}
// Struct holding references requires lifetimes
struct Excerpt<'a> {
part: &'a str,
}
Smart Pointers
Rust
123456789use std::rc::Rc;
use std::sync::Arc;
use std::cell::RefCell;
let boxed = Box::new(5); // Heap allocation
let shared = Rc::new(String::from("hi")); // Single-threaded ref counting
let atomic = Arc::new(42); // Thread-safe ref counting
let cell = RefCell::new(0); // Interior mutability
Concurrency
Rust
1234567891011121314151617181920212223242526272829303132333435363738394041use std::thread;
use std::sync::{mpsc, Arc, Mutex};
fn main() {
// Creating a thread
let handle = thread::spawn(|| {
println!("Thread work");
});
handle.join().unwrap();
// Channels for thread communication
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
tx.send(String::from("hi")).unwrap();
});
println!("{}", rx.recv().unwrap());
// Shared state with Arc + Mutex
let counter = Arc::new(Mutex::new(0));
let c = Arc::clone(&counter);
thread::spawn(move || {
*c.lock().unwrap() += 1;
});
// Scoped threads (stable since 1.63) — borrow non-'static data safely
let data = vec![1, 2, 3];
thread::scope(|s| {
s.spawn(|| println!("{:?}", &data));
});
}
// Async/Await (typically with tokio or async-std)
async fn fetch_data() -> Result<String, Box<dyn std::error::Error>> {
Ok("data".to_string())
}
// Async closures and async fn in traits are stable as of Rust 1.75+
trait AsyncProcessor {
async fn process(&self) -> u32;
}
Macros
Rust
123456789101112131415161718192021222324252627// Common built-in macros
println!("Hello, {}!", "world");
eprintln!("Error: {}", "oops");
format!("Value: {}", 42);
dbg!(x); // Debug-print with file/line info
todo!(); // Placeholder that panics
unimplemented!(); // Like todo!() but signals intentional gap
assert!(condition);
assert_eq!(a, b);
// Captured identifiers in format strings (stable since 1.58)
let name = "Rust";
println!("Hello, {name}!");
// Declarative macro
macro_rules! say_hello {
() => {
println!("Hello!");
};
($name:expr) => {
println!("Hello, {}!", $name);
};
}
say_hello!();
say_hello!("world");
Testing
Rust
123456789101112131415161718192021222324252627282930313233// Unit test
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
#[test]
#[should_panic(expected = "panic message")]
fn it_panics() {
panic!("panic message");
}
// Tests can return Result to use `?`
#[test]
fn parses() -> Result<(), std::num::ParseIntError> {
let n: i32 = "42".parse()?;
assert_eq!(n, 42);
Ok(())
}
#[test]
#[ignore = "slow"]
fn expensive_test() { /* ... */ }
}
// Run tests: cargo test
// Run ignored: cargo test -- --ignored
// Benchmark with criterion crate (stable Rust)
Cargo and Tooling
Bash
1234567891011121314cargo new my_project # Create a new binary crate
cargo new --lib my_lib # Create a new library crate
cargo build # Compile (debug)
cargo build --release # Optimized build
cargo run # Build and run
cargo check # Type-check without producing a binary
cargo test # Run tests
cargo fmt # Format code (rustfmt)
cargo clippy # Lint code
cargo doc --open # Build and open documentation
cargo add serde --features derive # Add a dependency (stable since 1.62)
cargo update # Update Cargo.lock
rustup update stable # Update toolchain
Cargo.toml should declare the edition (edition = "2024" for new projects on Rust 1.85+, otherwise "2021").
Common Libraries and Frameworks
- Tokio: Async runtime (de facto standard)
- Serde / serde_json: Serialization / deserialization
- Axum, actix-web, Rocket: Web frameworks
- reqwest: HTTP client
- sqlx, Diesel, SeaORM: Database access / ORMs
- clap: CLI argument parsing (derive API recommended)
- anyhow / thiserror: Error handling helpers
- tracing: Structured, async-aware logging and diagnostics
- rayon: Data parallelism for CPU-bound work
- criterion: Statistical benchmarking
Best Practices
- Use the latest stable toolchain via
rustupand pin an edition inCargo.toml - Run
cargo fmtandcargo clippy -- -D warningsin CI - Use
cargo checkduring iteration for faster feedback - Prefer immutability (
letoverlet mut) - Handle errors explicitly with
ResultandOption; use?to propagate - Use traits and generics for code reuse and zero-cost polymorphism
- Use
thiserrorfor library error types,anyhowfor application code - Write unit, integration (
tests/directory), and doc tests - Audit dependencies with
cargo auditand check licenses withcargo deny
Performance Tips
- Build with
--releaseand considerlto = "thin"andcodegen-units = 1inCargo.toml - Prefer borrowing (
&T) over cloning; useCow<'_, T>when ownership varies - Reach for iterators — they generally optimize as well as hand-written loops
- Use
rayonfor easy data parallelism on CPU-bound workloads - Profile with
cargo flamegraph,perf, orsamply; benchmark withcriterion - Use
#[inline]judiciously; the compiler usually makes good choices - Consider
Box<[T]>orSmallVecwhen you know size constraints
Resources for Further Learning
- Official Rust Book: https://doc.rust-lang.org/book/
- Rust by Example: https://doc.rust-lang.org/rust-by-example/
- Rustlings (Rust Learning Exercises): https://github.com/rust-lang/rustlings
- The Rust Reference: https://doc.rust-lang.org/reference/
- The Rustonomicon (unsafe Rust): https://doc.rust-lang.org/nomicon/
- Asynchronous Programming in Rust: https://rust-lang.github.io/async-book/
- This Week in Rust: https://this-week-in-rust.org/
- Rust Playground: https://play.rust-lang.org/
Continue Learning
Discover more cheatsheets to boost your productivity