Chào mừng các bạn đến với Lập trình Rust Cơ Bản! Nếu bạn đang tìm hiểu Ownership & Borrowing – hay còn gọi là Nguyên tắc sở hữu và mượn – thì bài viết này sẽ giúp bạn nắm bắt những khái niệm cốt lõi một cách dễ hiểu và thực tiễn.
Giới thiệu
Rust nổi tiếng với khả năng bảo vệ bộ nhớ mà không cần garbage collector. Điều này đạt được nhờ quản lý ownership (sở hữu) và borrowing (mượn) – hai nguyên tắc trung tâm của ngôn ngữ. Khi bạn hiểu và áp dụng đúng, bạn sẽ viết được code an toàn, nhanh chóng và không lo rò rỉ bộ nhớ.
1. Nguyên tắc sở hữu (Ownership) trong Rust
Ownership là “luật pháp” của Rust về cách dữ liệu được giữ và truyền đi. Ba quy tắc chính:
- Quy tắc 1: Mỗi giá trị có một owner duy nhất.
- Quy tắc 2: Khi owner ra khỏi phạm vi, giá trị sẽ bị
droptự động. - Quy tắc 3: Khi truyền giá trị sang biến khác, ownership được move (di chuyển) sang biến mới, và biến cũ không còn truy cập được.
Ví dụ minh họa
let s1 = String::from("Rust"); // s1 là owner
let s2 = s1; // ownership được move sang s2, s1 không còn hợp lệ
// println!("{}", s1); // lỗi biên dịch
2. Nguyên tắc mượn (Borrowing)
Borrowing cho phép bạn “mượn” dữ liệu mà không lấy quyền sở hữu, giúp tránh việc sao chép không cần thiết. Có hai loại borrowing:
- Borrowing bất biến (&) – nhiều phần tử có thể mượn cùng lúc, nhưng không được thay đổi dữ liệu.
- Borrowing có biến (&mut) – chỉ một phần tử có thể mượn có biến tại một thời điểm, và nó có thể thay đổi dữ liệu.
Quy tắc mượn
- Không được có đồng thời
&mutvà&cho cùng một dữ liệu. - Borrow phải kết thúc trước khi owner được sử dụng lại.
Ví dụ thực tế
let mut data = vec![1, 2, 3];
// Borrow bất biến
let slice = &data[..];
println!("Slice: {:?}", slice);
// Borrow có biến
let mutable_ref = &mut data;
mutable_ref.push(4);
println!("Data sau khi thay đổi: {:?}", mutable_ref);
3. Khi nào nên sử dụng Ownership vs Borrowing?
Việc quyết định giữa ownership và borrowing phụ thuộc vào mục tiêu của bạn:
- Ownership thích hợp khi bạn muốn chuyển giao toàn bộ dữ liệu hoặc tạo ra một chủ thể mới.
- Borrowing lý tưởng khi bạn chỉ cần đọc hoặc sửa đổi tạm thời mà không muốn mất quyền sở hữu.
4. Các tài nguyên hữu ích để học sâu hơn
Muốn khám phá thêm? Dưới đây là một vài nguồn tham khảo đáng tin cậy:
- Chương 4 – Understanding Ownership (Rust Book)
- Chương 4.2 – References and Borrowing
- Rust Standard Library – Borrow Trait
5. Thực hành nhanh: Bài tập Mini
Hãy thử tự viết một hàm nhận một &mut String, thêm một đoạn văn bản, và trả về độ dài của chuỗi. Đây là cách tốt để củng cố ownership & borrowing trong thực tế.
fn add_suffix(s: &mut String, suffix: &str) -> usize {
s.push_str(suffix);
s.len()
}
fn main() {
let mut greeting = String::from("Hello");
let len = add_suffix(&mut greeting, ", Rust!");
println!("{} (độ dài: {})", greeting, len);
}
Kết luận
Hiểu rõ nguyên tắc sở hữu và mượn là chìa khóa để thành thạo Lập trình Rust Cơ Bản. Khi bạn áp dụng đúng ownership & borrowing, code của bạn sẽ tránh được lỗi bộ nhớ, chạy nhanh hơn và dễ bảo trì hơn. Hãy tiếp tục thực hành, đọc tài liệu chính thức và chia sẻ kiến thức này với cộng đồng Rust!