-
Hello World
fn main() { println!("Hello, world!"); }
-
Comments
// This is a single-line comment /* * This is a multi-line comment */
-
Immutable Variable
let x = 5;
-
Mutable Variable
let mut y = 5; y = 6;
-
Constant
const MAX_POINTS: u32 = 100_000;
-
Scalar Types
- Integer:
i8
,i16
,i32
,i64
,i128
,isize
,u8
,u16
,u32
,u64
,u128
,usize
- Floating-point:
f32
,f64
- Character:
char
- Boolean:
bool
- Integer:
-
Compound Types
- Tuple
let tup: (i32, f64, u8) = (500, 6.4, 1); let (x, y, z) = tup;
- Array
let a = [1, 2, 3, 4, 5]; let first = a[0];
- Tuple
-
Basic Function
fn main() { let result = add(5, 3); println!("Result: {}", result); } fn add(x: i32, y: i32) -> i32 { x + y }
-
Functions with Multiple Returns
fn swap(x: i32, y: i32) -> (i32, i32) { (y, x) }
-
If-Else
if x < 5 { println!("x is less than 5"); } else { println!("x is 5 or greater"); }
-
Loop
loop { println!("Infinite loop"); break; }
-
While
while x < 10 { x += 1; }
-
For
for number in (1..4).rev() { println!("{}!", number); }
- Ownership and Borrowing
fn main() { let s1 = String::from("hello"); let s2 = s1; println!("{}", s2); // s1 is moved to s2, s1 is no longer valid } fn borrow_example(s: &String) { println!("{}", s); }
- Defining and Using Structs
struct User { username: String, email: String, sign_in_count: u64, active: bool, } let user1 = User { email: String::from("[email protected]"), username: String::from("someusername123"), active: true, sign_in_count: 1, };
- Defining and Using Enums
enum Message { Quit, Move { x: i32, y: i32 }, Write(String), ChangeColor(i32, i32, i32), } let msg = Message::Write(String::from("hello"));
- Match
let number = 7; match number { 1 => println!("One!"), 2 | 3 | 5 | 7 | 11 => println!("This is a prime"), 13..=19 => println!("A teen"), _ => println!("Ain't special"), }
-
Result Enum
use std::fs::File; use std::io::ErrorKind; fn main() { let f = File::open("hello.txt"); let _file = match f { Ok(file) => file, Err(ref error) if error.kind() == ErrorKind::NotFound => { File::create("hello.txt").unwrap_or_else(|error| { panic!("Problem creating the file: {:?}", error); }) }, Err(error) => { panic!("Problem opening the file: {:?}", error); } }; }
-
Panic
fn main() { panic!("Crash and burn"); }
- Defining and Using Modules
mod front_of_house { pub mod hosting { pub fn add_to_waitlist() {} } } pub fn eat_at_restaurant() { crate::front_of_house::hosting::add_to_waitlist(); }
- Cargo.toml
[package] name = "hello_world" version = "0.1.0" authors = ["Your Name <[email protected]>"] edition = "2021" [dependencies]
- Defining and Implementing Traits
pub trait Summary { fn summarize(&self) -> String; } pub struct NewsArticle { pub headline: String, pub location: String, pub author: String, pub content: String, } impl Summary for NewsArticle { fn summarize(&self) -> String { format!("{}, by {} ({})", self.headline, self.author, self.location) } }
- Using Generics
fn largest<T: PartialOrd>(list: &[T]) -> &T { let mut largest = &list[0]; for item in list { if item > largest { largest = item; } } largest }
- Specifying Lifetimes
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { if x.len() > y.len() { x } else { y } }
- Defining and Using Macros
macro_rules! say_hello { () => { println!("Hello!"); }; } fn main() { say_hello!(); }
-
Defining and Using Closures
let add_one = |x: i32| -> i32 { x + 1 }; println!("{}", add_one(5));
-
Closures with Environment Capture
let x = 4; let equal_to_x = |z| z == x; let y = 4; assert!(equal_to_x(y));
-
Creating and Using Iterators
let v1 = vec![1, 2, 3]; let v1_iter = v1.iter(); for val in v1_iter { println!("Got: {}", val); }
-
Using
map
andcollect
let v1: Vec<i32> = vec![1, 2, 3]; let v2: Vec<_> = v1.iter().map(|x| x + 1).collect();
-
Using
Box<T>
for Heap Allocationlet b = Box::new(5); println!("b = {}", b);
-
Using
Rc<T>
for Reference Countinguse std::rc::Rc; let a = Rc::new(5); let b = Rc::clone(&a); println!("count after creating b = {}", Rc::strong_count(&a));
-
Using
RefCell<T>
for Interior Mutabilityuse std::cell::RefCell; let x = RefCell::new(5); *x.borrow_mut() += 1; println!("x = {:?}", x.borrow());
-
Using Threads
use std::thread; use std::time::Duration; let handle = thread::spawn(|| { for i in 1..10 { println!("hi number {} from the spawned thread!", i); thread::sleep(Duration::from_millis(1)); } }); for i in 1..5 { println!("hi number {} from the main thread!", i); thread::sleep(Duration::from_millis(1)); } handle.join().unwrap();
-
Using Channels
use std::sync::mpsc; use std::thread; let (tx, rx) = mpsc::channel(); thread::spawn(move || { let val = String::from("hi"); tx.send(val).unwrap(); }); let received = rx.recv().unwrap(); println!("Got: {}", received);
-
Using Unsafe Code
let mut num = 5; let r1 = &num as *const i32; let r2 = &mut num as *mut i32; unsafe { println!("r1 is: {}", *r1); println!("r2 is: {}", *r2); }
-
Calling Unsafe Functions
unsafe fn dangerous() {} unsafe { dangerous(); }
- Trait Objects for Dynamic Dispatch
pub trait Draw { fn draw(&self); } pub struct Screen { pub components: Vec<Box<dyn Draw>>, } impl Screen { pub fn run(&self) { for component in self.components.iter() { component.draw(); } } }
-
Using Derive Macros
#[derive(Debug)] struct Rectangle { width: u32, height: u32, } fn main() { let rect1 = Rectangle { width: 30, height: 50, }; println!("rect1 is {:?}", rect1); }
-
Custom Attributes
#[cfg(test)] mod tests { #[test] fn it_works() { assert_eq!(2 + 2, 4); } }
- Using async/await
use tokio::time::{sleep, Duration}; #[tokio::main] async fn main() { async fn say_hello() { sleep(Duration::from_secs(1)).await; println!("Hello, world!"); } say_hello().await; }
Rust doesn't have built-in support for dependency injection (DI) like some other languages, but DI can be achieved through various patterns and libraries. Here’s a simple example using traits and structs:
- Simple Dependency Injection
trait Messenger { fn send(&self, msg: &str); } struct Email; impl Messenger for Email { fn send(&self, msg: &str) { println!("Sending email: {}", msg); } } struct Logger<M: Messenger> { messenger: M, } impl<M: Messenger> Logger<M> { fn log(&self, msg: &str) { self.messenger.send(msg); } } fn main() { let email = Email; let logger = Logger { messenger: email }; logger.log("Hello, Dependency Injection!"); }
- Using Cargo to Install Packages
-
Add the dependency in
Cargo.toml
:[dependencies] rand = "0.8"
-
Use the package in your project:
use rand::Rng; fn main() { let mut rng = rand::thread_rng(); let n: u32 = rng.gen(); println!("Random number: {}", n); }
-
-
Type Aliases
type Kilometers = i32; let x: Kilometers = 5;
-
Newtype Pattern
struct Wrapper(Vec<String>); impl Wrapper { pub fn new() -> Wrapper { Wrapper(Vec::new()) } }
-
Destructuring Structs
struct Point { x: i32, y: i32, } let p = Point { x: 0, y: 7 }; let Point { x, y } = p;
-
Destructuring Enums
enum Message { Quit, Move { x: i32, y: i32 }, Write(String), ChangeColor(i32, i32, i32), } let msg = Message::ChangeColor(0, 160, 255); match msg { Message::Quit => println!("The Quit variant has no data to destructure."), Message::Move { x, y } => println!("Move in the x direction {} and in the y direction {}", x, y), Message::Write(text) => println!("Text message: {}", text), Message::ChangeColor(r, g, b) => println!("Change the color to red {}, green {}, and blue {}", r, g, b), }
- Using Inline Assembly
unsafe { asm!("nop"); }
- Accessing and Modifying a Mutable Static Variable
static mut COUNTER: u32 = 0; fn add_to_count(inc: u32) { unsafe { COUNTER += inc; } } fn main() { add_to_count(3); unsafe { println!("COUNTER: {}", COUNTER); } }
- Creating a Procedural Macro
-
Define the macro in a separate crate:
// in src/lib.rs extern crate proc_macro; use proc_macro::TokenStream; use quote::quote; use syn; #[proc_macro] pub fn make_hello(item: TokenStream) -> TokenStream { let input = syn::parse_macro_input!(item as syn::LitStr); let expanded = quote! { println!("Hello, {}!", #input); }; TokenStream::from(expanded) }
-
Use the macro in your main project:
use my_macro::make_hello; fn main() { make_hello!("world"); }
-
- Using Feature Flags in Cargo
-
Define features in
Cargo.toml
:[features] default = [] secure = ["ring"]
-
Conditional Compilation:
#[cfg(feature = "secure")] fn secure_function() { println!("Secure function enabled"); } #[cfg(not(feature = "secure"))] fn secure_function() { println!("Secure function not enabled"); }
-
- Using
From
andInto
Traitsimpl From<i32> for Point { fn from(item: i32) -> Self { Point { x: item, y: item } } } let p: Point = 5.into();
- Implementing the Default Trait
#[derive(Debug)] struct Point { x: i32, y: i32, } impl Default for Point { fn default() -> Self { Point { x: 0, y: 0 } } } fn main() { let origin: Point = Default::default(); println!("Origin: {:?}", origin); }