π Hello World
fn main() {
println!("Hello, world!");
}
π‘ Tip: Use println! macro for output in Rust.
π¦ Variables & Data Types
fn main() {
let age: i32 = 21;
let pi: f64 = 3.14159;
let grade: char = 'A';
let name: &str = "Maxon";
println!("{} is {} years old.", name, age);
}
π‘ Tip: Variables are immutable by default. Use mut for mutability.
π Control Flow
fn main() {
for i in 1..=5 {
if i % 2 == 0 {
println!("{} is even", i);
} else {
println!("{} is odd", i);
}
}
}
π‘ Tip: Use if, else if, match, loop, and while for control flow.
π Functions
fn add(a: i32, b: i32) -> i32 {
a + b
}
fn main() {
println!("Sum: {}", add(5, 3));
}
π‘ Tip: Functions return the last expression automatically (no return needed).
π Structs
struct Car {
brand: String,
speed: u32,
}
impl Car {
fn drive(&self) {
println!("{} drives at {} km/h", self.brand, self.speed);
}
}
fn main() {
let car = Car { brand: String::from("Tesla"), speed: 120 };
car.drive();
}
π‘ Tip: Use impl blocks to define methods on structs.
π§© Enums
enum Direction {
Up,
Down,
Left,
Right,
}
fn main() {
let dir = Direction::Up;
match dir {
Direction::Up => println!("Going Up!"),
Direction::Down => println!("Going Down!"),
_ => println!("Left or Right!"),
}
}
π‘ Tip: match is exhaustive — all variants must be covered.
π Ownership & Borrowing
fn main() {
let s1 = String::from("Hello");
let s2 = s1; // Ownership moved!
// println!("{}", s1); // ❌ Error: value borrowed after move
println!("{}", s2);
}
π‘ Tip: Use & for borrowing to avoid moving ownership.
π References
fn main() {
let x = 10;
let r = &x;
println!("Reference: {}", r);
}
π‘ Tip: References (&) do not take ownership. Use &mut for mutable references.
π§ Traits
trait Greet {
fn say_hello(&self);
}
struct Person {
name: String,
}
impl Greet for Person {
fn say_hello(&self) {
println!("Hello, {}!", self.name);
}
}
fn main() {
let p = Person { name: String::from("Maxon") };
p.say_hello();
}
π‘ Tip: Traits are like interfaces in other languages.
π¦ Generics
fn add<T: std::ops::Add<Output = T>>(a: T, b: T) -> T {
a + b
}
fn main() {
println!("{}", add(5, 3));
println!("{}", add(2.5, 1.2));
}
π‘ Tip: Generics let you write flexible, type-safe code.
π Collections
use std::collections::HashMap;
fn main() {
let mut nums = vec![1, 2, 3];
nums.push(4);
println!("{:?}", nums);
let mut scores = HashMap::new();
scores.insert("Alice", 90);
scores.insert("Bob", 85);
println!("{:?}", scores);
}
π‘ Tip: Common collections: Vec, HashMap, HashSet.
π File Handling
use std::fs::File;
use std::io::prelude::*;
fn main() -> std::io::Result<()> {
let mut file = File::create("data.txt")?;
file.write_all(b"Hello File!")?;
let mut f = File::open("data.txt")?;
let mut contents = String::new();
f.read_to_string(&mut contents)?;
println!("{}", contents);
Ok(())
}
π‘ Tip: The ? operator propagates errors easily.
⚡ Closures
fn main() {
let square = |x: i32| x * x;
println!("{}", square(5));
}
π‘ Tip: Closures can capture variables from their environment.
π§ Smart Pointers
use std::rc::Rc;
use std::cell::RefCell;
fn main() {
let value = Rc::new(RefCell::new(42));
*value.borrow_mut() += 1;
println!("{}", value.borrow());
}
π‘ Tip: Use Rc for reference counting and RefCell for interior mutability.