Borrowing in Rust
In layman's terms, please explain borrowing in Rust, then present a well commented coding example to help the reader to better understand the term.
Borrowing in Rust: A Simple Explanation
In Rust, "borrowing" refers to the process of allowing a function or part of your program to temporarily access a variable without taking ownership of it. This ensures that you can use data without moving it, which would otherwise make it unusable in the original scope.
Rust uses two types of borrowing:
- Immutable Borrowing (
&
): You can borrow the value of a variable, but you cannot modify it. Multiple immutable borrows are allowed. - Mutable Borrowing (
&mut
): You can borrow the value and modify it, but only one mutable borrow is allowed at a time to prevent data races and ensure safety.
The rules of borrowing in Rust are:
- You can have multiple immutable borrows (
&
) OR - You can have one mutable borrow (
&mut
), but not both at the same time.
This ensures memory safety by preventing unexpected changes to data while it is being used elsewhere.
Example Code
// Create a variable with ownership of a string
let mut my_string = String::from("Hello, Rust!");
// Borrow the value immutably (cannot modify)
// We can have multiple immutable borrows
let length = calculate_length(&my_string); // Passing a reference to my_string
println!("The length of '{}' is {}.", my_string, length);
// Mutable borrow (can modify the value)
// Only one mutable borrow is allowed at a time
append_world(&mut my_string); // Passing a mutable reference
println!("After modification: '{}'", my_string);
}
// Function that takes an immutable reference to a string
// It can read the string but cannot modify it
fn calculate_length(s: &String) -> usize {
s.len() // Return the length of the string
}
// Function that takes a mutable reference to a string
// It can modify the original string
fn append_world(s: &mut String) {
s.push_str(" World!"); // Appends " World!" to the string
}
Commented Explanation of the Code
We declare a
mut
variablemy_string
so it can be modified later.Immutable Borrowing:
- In the
calculate_length
function, we pass&my_string
. This is an immutable reference. The function can accessmy_string
but not change it. - Multiple immutable references (borrows) can exist, so you can call the
calculate_length
function as many times as you want without changing the original data.
- In the
Mutable Borrowing:
- In the
append_world
function, we pass&mut my_string
, which allows us to modify the original string by appending" World!"
to it. - Only one mutable borrow can exist at a time, which prevents data races and keeps your program safe from unexpected behavior.
- In the
This combination of borrowing rules helps Rust ensure memory safety without needing a garbage collector.