- Introduction to Rust
- Installation
- Hello, World!
- Variables and Constants
- Data Types
- Functions
- Control Flow
- Ownership
- References and Borrowing
- Slices
- Structs
- Enums
- Pattern Matching
- Modules and Packages
- Collections
- Error Handling
- Generics
- Traits
- Lifetimes
- Smart Pointers
- Concurrency
- Macros
- Crates and Cargo
- Testing
- Documentation
- Best Practices
Rust is a systems programming language focused on safety, speed, and concurrency. It achieves memory safety without a garbage collector and is designed to be both fast and safe.
To install Rust, use rustup
, the Rust toolchain installer:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
After installation, you can update Rust with:
rustup update
Create a new Rust project using Cargo:
cargo new hello_world
cd hello_world
Edit src/main.rs
:
fn main() {
println!("Hello, world!");
}
Run the program:
cargo run
fn main() {
let mut x = 5;
println!("The value of x is: {}", x);
x = 6;
println!("The value of x is: {}", x);
}
const MAX_POINTS: u32 = 100_000;
- Integer
- Floating-point
- Boolean
- Character
- Tuple
- Array
fn main() {
let x: i32 = 42;
let y: f64 = 3.14;
let is_active: bool = true;
let character: char = 'A';
let tuple: (i32, f64, u8) = (500, 6.4, 1);
let array: [i32; 3] = [1, 2, 3];
}
fn main() {
another_function();
}
fn another_function() {
println!("Another function.");
}
fn main() {
print_value(5);
}
fn print_value(x: i32) {
println!("The value is: {}", x);
}
fn main() {
let x = five();
println!("The value of x is: {}", x);
}
fn five() -> i32 {
5
}
fn main() {
let number = 6;
if number % 4 == 0 {
println!("number is divisible by 4");
} else if number % 3 == 0 {
println!("number is divisible by 3");
} else {
println!("number is not divisible by 4, 3, or 2");
}
}
loop
while
for
fn main() {
let mut counter = 0;
let result = loop {
counter += 1;
if counter == 10 {
break counter * 2;
}
};
println!("The result is {}", result);
let mut number = 3;
while number != 0 {
println!("{}!", number);
number -= 1;
}
let a = [10, 20, 30, 40, 50];
for element in a.iter() {
println!("the value is: {}", element);
}
}
- Each value in Rust has a variable that’s called its owner.
- There can only be one owner at a time.
- When the owner goes out of scope, the value will be dropped.
fn main() {
let s1 = String::from("hello");
let s2 = s1;
// println!("{}", s1); // This will cause an error
}
fn main() {
let s1 = String::from("hello");
let len = calculate_length(&s1);
println!("The length of '{}' is {}.", s1, len);
}
fn calculate_length(s: &String) -> usize {
s.len()
}
fn main() {
let mut s = String::from("hello");
change(&mut s);
}
fn change(some_string: &mut String) {
some_string.push_str(", world");
}
Slices let you reference a contiguous sequence of elements in a collection rather than the whole collection.
fn main() {
let s = String::from("hello world");
let hello = &s[0..5];
let world = &s[6..11];
println!("{} {}", hello, world);
}
fn main() {
let a = [1, 2, 3, 4, 5];
let slice = &a[1..3];
println!("{:?}", slice);
}
struct User {
username: String,
email: String,
sign_in_count: u64,
active: bool,
}
fn main() {
let user1 = User {
email: String::from("[email protected]"),
username: String::from("someusername123"),
active: true,
sign_in_count: 1,
};
}
impl User {
fn full_name(&self) -> String {
format!("{} <{}>", self.username, self.email)
}
}
fn main() {
let user1 = User {
email: String::from("[email protected]"),
username: String::from("someusername123"),
active: true,
sign_in_count: 1,
};
println!("{}", user1.full_name());
}
enum IpAddrKind {
V4,
V6,
}
fn main() {
let four = IpAddrKind::V4;
let six = IpAddrKind::V6;
}
enum IpAddr {
V4(String),
V6(String),
}
fn main() {
let home = IpAddr::V4(String::from("127.0.0.1"));
let loopback = IpAddr::V6(String::from("::1"));
}
enum Coin {
Penny,
Nickel,
Dime,
Quarter,
}
fn value_in_cents(coin: Coin) -> u32 {
match coin {
Coin::Penny => 1,
Coin::Nickel => 5,
Coin::Dime => 10,
Coin::Quarter => 25,
}
}
fn main() {
let some_value = Some(3);
if let Some(3) = some_value {
println!("Three");
}
}
mod front_of_house {
pub mod hosting {
pub fn add_to_waitlist() {}
}
}
fn main() {
crate::front_of_house::hosting::add_to_waitlist();
}
Packages are a collection of crates. A crate can be a binary or a library.
fn main() {
let v: Vec<i32> = Vec::new();
let v = vec![1, 2, 3];
}
fn main() {
let mut s = String::from("foo");
s.push_str("bar");
}
use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
}
use std::fs
::File;
use std::io::ErrorKind;
fn main() {
let f = File::open("hello.txt");
let _f = match f {
Ok(file) => file,
Err(error) => match error.kind() {
ErrorKind::NotFound => match File::create("hello.txt") {
Ok(fc) => fc,
Err(e) => panic!("Problem creating the file: {:?}", e),
},
other_error => panic!("Problem opening the file: {:?}", other_error),
},
};
}
fn main() {
panic!("crash and burn");
}
fn largest<T: PartialOrd>(list: &[T]) -> &T {
let mut largest = &list[0];
for item in list {
if item > largest {
largest = item;
}
}
largest
}
pub trait Summary {
fn summarize(&self) -> String;
}
pub struct Article {
pub headline: String,
pub content: String,
}
impl Summary for Article {
fn summarize(&self) -> String {
format!("{}, {}", self.headline, self.content)
}
}
pub trait Summary {
fn summarize(&self) -> String {
String::from("(Read more...)")
}
}
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
struct ImportantExcerpt<'a> {
part: &'a str,
}
fn main() {
let novel = String::from("Call me Ishmael. Some years ago...");
let first_sentence = novel.split('.').next().expect("Could not find a '.'");
let i = ImportantExcerpt { part: first_sentence };
}
fn main() {
let b = Box::new(5);
println!("b = {}", b);
}
use std::rc::Rc;
fn main() {
let a = Rc::new(5);
let b = Rc::clone(&a);
println!("a = {}, b = {}", a, b);
}
use std::cell::RefCell;
fn main() {
let x = RefCell::new(5);
*x.borrow_mut() += 1;
println!("x = {:?}", x);
}
use std::thread;
use std::time::Duration;
fn main() {
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();
}
use std::sync::mpsc;
use std::thread;
fn main() {
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);
}
macro_rules! say_hello {
() => {
println!("Hello!");
};
}
fn main() {
say_hello!();
}
Procedural macros are more complex and typically used for code generation.
cargo new my_crate
cargo build
cargo run
Add dependencies in Cargo.toml
:
[dependencies]
serde = "1.0"
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}
cargo test
Use ///
for documentation comments:
/// Adds one to the given number.
///
/// # Examples
///
/// ```
/// let five = 5;
/// assert_eq!(6, add_one(five));
/// ```
fn add_one(x: i32) -> i32 {
x + 1
}
cargo doc --open
- Write Idiomatic Rust: Follow Rust conventions and idioms.
- Use
rustfmt
: Automatically format your code. - Use
clippy
: Catch common mistakes and improve your Rust code. - Document Your Code: Write clear and concise documentation.
- Test Thoroughly: Write tests for all critical code paths.
- Handle Errors Gracefully: Use
Result
andOption
effectively. - Keep Dependencies Updated: Regularly update and audit dependencies.
- Learn from the Community: Engage with the Rust community for best practices and support.
This tutorial provides a comprehensive overview of Rust, from basic concepts to advanced techniques. By mastering these topics, you'll be able to write safe, concurrent, and efficient Rust programs.
Here is a link to a Youtube Tutorial which can help you learn the language in a better way <>
https://youtu.be/BpPEoZW5IiY?si=jPOCC5yanWbrFIAL