27/04/2026 03:20am

Understanding Borrowing and References | Rust The Series EP.8
#Rust Borrowing
#References
#Rust
#Rust tutorial
Welcome back, fellow developers, to Rust The Series! In EP.7, we witnessed the strict (but safe) rules of Ownership. We saw how moving a value causes the original variable to "die" instantly. You might be feeling a bit frustrated and asking yourself:
"Do I really have to call
.clone()and waste memory every time I want to pass data to a function? Or do I have to return the value back every single time just to give ownership back to the original variable?"
The answer is "Absolutely not!" Rust provides a sophisticated system called Borrowing, powered by References (&), designed to make our lives much easier.
1. Immutable References (Read-Only Borrowing)
Borrowing in Rust is just like "borrowing a book from a library":
You can read it (Access the data).
You do not own it (No Ownership).
Most importantly: You are strictly forbidden from writing or modifying the content!
In Rust, we use the & symbol before a variable name to tell the compiler: "This is a reference. I’m just letting the function borrow it for a look; I’m not giving away the ownership."
Rust
fn main() {
let s1 = String::from("Superdev");
// Passing &s1 means we are "lending" the data
let len = calculate_length(&s1);
// ✅ s1 is still valid! Ownership remains here in the main function.
println!("The length of '{}' is {}.", s1, len);
}
fn calculate_length(s: &String) -> usize { // Parameter is a Reference (&)
s.len()
} // Here, s goes out of scope.
// However, the actual data is NOT deleted because s was only a borrower, not the owner.
💡 Pro Tip: Notice that when calling
calculate_length(&s1), we use the&symbol, and the function signature(s: &String)also requires the&. This acts as a "contract" between the sender and the receiver, both agreeing that "this is just a loan."
2. Modifying Data: Mutable References (&mut)
If an immutable reference is for "reading," a Mutable Reference is for "borrowing to edit." Imagine borrowing a book from a friend and asking, "Hey, do you mind if I take some notes inside?" Your friend can only say yes if they (the owner) decided the book was "writable" (mutable) from the very beginning.
In Rust, we use the &mut symbol for this. However, there is one crucial condition: The original variable must be declared as mut first.
Rust
fn main() {
// 1. The original variable must be 'mut' to allow others to modify it.
let mut s = String::from("Hello");
// 2. When passing it, you must use '&mut' to confirm you are "lending it for modification."
change(&mut s);
println!("{}", s); // Result: "Hello, Superdev"
}
fn change(some_string: &mut String) { // 3. The receiver must specify '&mut String'
some_string.push_str(", Superdev");
}
⚠️ Warning: While you can borrow to edit, Rust is stricter than your average friend. The compiler enforces a major rule: "You can only have one mutable reference (&mut) to a piece of data at a time." No one else can borrow it (even just to read) while someone is editing it. We’ll dive into the "why" behind this in the next section.
3. The Rules of Borrowing
To ensure maximum safety and prevent every programmer’s nightmare—Data Races (where data is modified simultaneously, causing crashes or corruption)—Rust enforces two ironclad rules that the compiler checks every time:
Rule 1: Many Readers OR One Writer
At any given time, you can have only one of these two situations:
Multiple "Readers" (
&): You can have as many immutable references as you want. It’s like reading a Wikipedia page; everyone can read it simultaneously because the content isn't changing.Exactly ONE "Writer" (
&mut): You can have only one mutable reference. While this person is "writing" or "editing," no one else is allowed to even look at the data.
Rule 2: References Must Always Be Valid (No Dangling References)
You cannot borrow something from someone who no longer exists. A reference must never outlive the actual owner of the data in memory.
Let’s look at an example that will make the compiler scream at us:
Rust
fn main() {
let mut s = String::from("hello");
let r1 = &s; // ✅ Borrowing to read (OK)
let r2 = &s; // ✅ Borrowing to read (OK)
// ❌ ERROR! The compiler will stop you right here.
let r3 = &mut s;
println!("{}, {}, and {}", r1, r2, r3);
}
Why does this fail?
Imagine r1 and r2 are focused on reading a piece of paper. Suddenly, r3 walks up and starts crossing out words and writing new ones right in front of them! The information r1 and r2 were just reading is now invalid and inconsistent.
Rust stops this chaos at the source: "If someone is reading, no one can edit" and "If someone is editing, no one else can read." This guarantees that the data in your hand is 100% accurate and safe, always.
4. Why Suffer Through These Rules? (The Benefits)
You might be thinking, "Man, that’s a lot of rules!" But trust me, once you master them, you’ll be writing world-class code that reaps these massive rewards:
🚀 Extreme Performance: We no longer waste time or resources on heavy
.clone()operations or copying large data on the Heap every time we pass it to a function. Using a Reference is simply passing a small "address" (Pointer), which is incredibly fast.🛡️ Top-Tier Safety: Rust’s Borrow Checker audits your code’s safety while you write it. You don't have to cross your fingers and hope the program doesn't crash at Runtime. You can rest easy knowing that no one is "editing data behind your back."
💎 Clean Code & Better DX (Developer Experience): Your code becomes more readable and natural. You won’t need to write awkward functions that constantly return the original value just to maintain Ownership.
Summary
The Borrowing system is the heart of what makes Rust both practical and incredibly powerful. While the rules might feel a bit "picky" at first, once you get into the rhythm of identifying "Who is the owner?" and "Who is just borrowing?", you'll find yourself writing lightning-fast code. Your programs will be immune to memory corruption and, most importantly, "completely free of memory leaks"—all without ever needing a Garbage Collector!
📌 In the next episode (EP.9): We’ll keep the momentum going with Slices. You'll learn how to "borrow" only a specific portion of data (for example, how to grab just the first word of a long sentence). This technique will elevate your ability to manage Arrays and Strings to a professional level... See you there! 🦀✨
🎯 Follow Superdev Academy for top-tier Dev knowledge: Don't miss out on deep-dive technical articles and the latest updates from the Superdev Academy team. Follow us on all our channels here:
🔵 Facebook: Superdev Academy Thailand
🎬 YouTube: Superdev Academy Channel
📸 Instagram: @superdevacademy
🎬 TikTok: @superdevacademy
🌐 Website: superdevacademy.com