Rust - Introduction
Overview
Estimated time: 30–45 minutes
Rust is a systems programming language that runs blazingly fast, prevents segfaults, and guarantees thread safety. This introduction orients you to Rust's unique approach to memory safety without garbage collection, its growing ecosystem, and what you'll learn in this comprehensive tutorial series.
Learning Objectives
- Understand what makes Rust unique: memory safety, performance, and concurrency.
- Learn about Rust's ownership system and zero-cost abstractions.
- Explore Rust's ecosystem and common use cases.
- Know the immediate next steps: installing Rust and writing your first program.
Prerequisites
- None. This is the first lesson.
- Basic programming experience in any language is helpful but not required.
Why Rust?
Memory Safety Without Garbage Collection
Rust prevents common programming errors like null pointer dereferences, buffer overflows, and memory leaks at compile time, without the runtime overhead of a garbage collector.
Zero-Cost Abstractions
High-level features compile down to the same assembly you'd write by hand. You don't pay a runtime cost for abstractions.
Fearless Concurrency
Rust's ownership system enables safe concurrent programming by preventing data races at compile time.
Example: Hello, Rust!
fn main() {
println!("Hello, Rust!");
}
Expected Output:
Hello, Rust!
Rust's Unique Features
Ownership System
Rust tracks ownership of memory through its type system, eliminating the need for manual memory management or garbage collection:
fn main() {
let s1 = String::from("hello");
let s2 = s1; // s1 is moved to s2
// println!("{}", s1); // This would cause a compile error!
println!("{}", s2); // This works fine
}
Expected Output:
hello
Pattern Matching
Exhaustive pattern matching ensures you handle all possible cases:
enum Coin {
Penny,
Nickel,
Dime,
Quarter,
}
fn value_in_cents(coin: Coin) -> u8 {
match coin {
Coin::Penny => 1,
Coin::Nickel => 5,
Coin::Dime => 10,
Coin::Quarter => 25,
}
}
fn main() {
let coin = Coin::Dime;
println!("Value: {} cents", value_in_cents(coin));
}
Expected Output:
Value: 10 cents
Error Handling
Rust forces you to handle errors explicitly using Result
and Option
types:
fn divide(x: f64, y: f64) -> Result {
if y == 0.0 {
Err("Cannot divide by zero".to_string())
} else {
Ok(x / y)
}
}
fn main() {
match divide(10.0, 2.0) {
Ok(result) => println!("Result: {}", result),
Err(error) => println!("Error: {}", error),
}
match divide(10.0, 0.0) {
Ok(result) => println!("Result: {}", result),
Err(error) => println!("Error: {}", error),
}
}
Expected Output:
Result: 5
Error: Cannot divide by zero
Common Use Cases for Rust
Systems Programming
- Operating Systems: Redox OS, parts of Linux kernel
- Web Browsers: Firefox's Servo engine
- Game Engines: Bevy, Amethyst
Web Development
- Web Servers: actix-web, axum, warp
- WebAssembly: Rust compiles to fast WASM
- Microservices: Fast, safe, concurrent services
Command Line Tools
- Developer Tools: ripgrep, exa, bat, fd
- Build Tools: cargo, just
- Network Tools: custom CLI applications
Blockchain & Cryptocurrency
- Blockchains: Solana, Polkadot, Near
- Smart Contracts: Solana programs
- Crypto Libraries: ring, rustls
The Rust Ecosystem
Cargo Package Manager
Cargo handles dependencies, builds, testing, and publishing. It's built into Rust from day one.
Crates.io
The official package registry with over 100,000 community crates (libraries).
Popular Crates
- serde: Serialization/deserialization
- tokio: Async runtime
- clap: Command-line argument parsing
- reqwest: HTTP client
- anyhow: Error handling
Rust Editions
Rust releases new "editions" every 3 years to introduce breaking changes in a controlled way:
- 2015: First stable release (Rust 1.0)
- 2018: Module system improvements, async/await preparation
- 2021: Async/await stabilization, disjoint captures
Performance Characteristics
Memory Usage
Rust programs typically use less memory than garbage-collected languages because:
- No garbage collector overhead
- Stack allocation by default
- Efficient data structures
Runtime Performance
Rust often matches or exceeds C/C++ performance because:
- Zero-cost abstractions
- Aggressive compile-time optimization
- No runtime type checking
Compile Times
Rust compilation is slower than some languages due to:
- Extensive compile-time checks
- Monomorphization of generics
- Link-time optimization
Learning Path Overview
Beginner Track (First 10 tutorials)
- Installation & tooling setup
- First program and basic syntax
- Variables, data types, and functions
- Control flow and pattern matching
- Ownership and borrowing concepts
Intermediate Track
- Structs, enums, and methods
- Error handling with Result and Option
- Traits and generics
- Collections and iterators
- Module system and crates
Advanced Track
- Lifetimes and advanced borrowing
- Concurrency and async programming
- Unsafe Rust
- Macros and metaprogramming
- Performance optimization
Architect Track
- API design principles
- Code organization and architecture
- Testing strategies
- Build and deployment
- Ecosystem and tooling
Common Pitfalls for Beginners
Fighting the Borrow Checker
New Rustaceans often struggle with ownership concepts. The borrow checker is your friend—it prevents bugs!
Over-using clone()
Cloning data to satisfy the borrow checker isn't always the best solution. Learn borrowing patterns first.
Expecting Garbage Collection
Coming from GC languages, you need to think about ownership and lifetimes explicitly.
Ignoring the Type System
Rust's type system is powerful. Use Option
and Result
instead of panicking.
Development Environment
Editor Support
- VS Code: rust-analyzer extension
- IntelliJ IDEA: Rust plugin
- Vim/Neovim: rust.vim, CoC, or LSP
- Emacs: rust-mode with LSP
Toolchain
- rustc: The Rust compiler
- cargo: Package manager and build tool
- rustfmt: Code formatter
- clippy: Linter for catching common mistakes
Community and Resources
Official Resources
- The Rust Book: Comprehensive official guide
- Rust by Example: Learn by running code
- Rustonomicon: Unsafe Rust guide
Community
- Users Forum: users.rust-lang.org
- Discord: Active community chat
- Reddit: r/rust subreddit
- This Week in Rust: Weekly newsletter
Checks for Understanding
- What are the three main goals of Rust? (Memory safety, performance, concurrency)
- How does Rust achieve memory safety without garbage collection? (Ownership system)
- What is a zero-cost abstraction? (High-level features that compile to efficient code)
- Name three common use cases for Rust. (Systems programming, web services, CLI tools)
- What is the difference between
Result
andOption
? (Result for errors, Option for nullable values)
Answers
- Memory safety, performance, and concurrency
- Through its ownership system that tracks memory usage at compile time
- A feature that provides convenience without runtime cost
- Systems programming, web development, command-line tools, blockchain, etc.
- Result handles success/error cases, Option handles some/none cases