Rust from Basics to Mastery — Part 1
Managing memory safely with ownership and borrowing
The articles written on this blog were created with the goal of teaching. Also, the information in the article may be incorrect, so please be careful.
Rust is a systems programming language that aims to maintain memory safety without a garbage collector. When creating programs where performance is important, we try to reduce invalid pointers and data races at the compilation stage.
Values have owners
Values in Rust have one owner by default. Values are automatically cleaned up when the owner goes out of scope.
fn main() {
let name = String::from("Rose");
print_name(name);
// Ownership of name has moved to the function.
}
fn print_name(value: String) {
println!("{value}");
}
When a String is passed to a function by value, ownership moves. If the caller wants to keep using it, the value can be borrowed instead.
Borrow a value by reference
fn main() {
let name = String::from("Rose");
print_name(&name);
println!("{name}");
}
fn print_name(value: &String) {
println!("{value}");
}
&String is a reference that can read a value without owning it. To change the value, use a mutable reference such as &mut String.
The rules that prevent you from creating multiple mutable references at the same time are tricky at first. Instead, it prevents incorrect memory access and race conditions that may occur during execution.
Express the possibility of failure as a type
Rust frequently uses Option<T> when a value may be absent and Result<T, E> when an operation may fail.
fn divide(a: i32, b: i32) -> Result<i32, String> {
if b == 0 {
return Err(String::from("It cannot be divided by 0."));
}
Ok(a / b)
}
The calling code must explicitly handle success and failure. Safety in Rust also includes making errors difficult to ignore.
Rust projects are managed with Cargo commands such as cargo new, cargo run, and cargo test. At first, rather than trying to memorize all the ownership rules, it is better to create a small command line program and follow the compiler messages to check the scope of the borrow.