· Phạm Thành Nam · Ngôn ngữ Rust · 4 phút đọc

30 Ngày học Rust - Day 17: Quyền năng của Smart Pointers

Day 17: Khi References mặc định không đủ sức mạnh. Khám phá cách Box cấp phát RAM trên Heap, cách Rc nhân bản Quyền Sở Hữu, và cách RefCell bẻ cong định luật Rust.

Day 17: Khi References mặc định không đủ sức mạnh. Khám phá cách Box cấp phát RAM trên Heap, cách Rc nhân bản Quyền Sở Hữu, và cách RefCell bẻ cong định luật Rust.

Khi Con Trỏ Bình Thường Bất Lực

Các tham chiếu (References &&mut) mà chúng ta học ở Ngày 5 là những Trọng Binh cơ bản. Chúng chỉ cầm Địa chỉ để ngó dữ liệu. Nhưng chúng không sở hữu Mảnh đất đó và không có năng lực gọi GC vứt Rác (Drop memory).

Để xây dựng Cây Dữ Liệu (Trees) hay Đồ Thị Phức Tạp (Graphs) - nơi mà các cục Data móc vào nhau chằng chịt, Trình Biên Dịch của Rust sẽ hoảng loạn và báo Lỗi vì Giao Thức Mượn / Trả của nó bị Gẫy Chéo. Đó là lúc Smart Pointers (Con trỏ thông minh) tỏa sáng. Khác với &, Smart Pointers là Cục Data Sở hữu (Owner).

Minh hoạ cấu trúc bao bọc của Smart Pointers

1. Box<T> - Đẩy mọi thứ ra The Heap

Dữ liệu cục bộ tạo ra trong Hàm sẽ lưu ở Stack (Cực nhanh nhưng nhỏ). Nhưng nếu bạn cố tình tạo một cấu trúc dữ liệu Lồng lúp Vô Tận kiểu Danh Sách Liên Kết, Rust cấm cửa bạn: struct Node { so: i32, next: Node } -> Compiler sẽ Gào thét: Tao không biết cái Struct này Bự bao nhiêu Megabytes, Không cho chạy!

Giải pháp là bọc nó vào Cỗ Xe Box:

struct Node {
    so: i32,
    next: Option<Box<Node>>, // Giờ thì Mày chỉ lưu 1 Điểm Tham Cố định Bằng Cái Box
}

fn main() {
    let _b = Box::new(5); // Cưỡng ép số 5 Phải Lưu Bỏ Ở bãi Rác Khổng Lồ The Heap
}

Nhờ Box, kích thước Node giờ là Tĩnh (Chỉ chứa 1 Con Số và 1 Sợi Dây Trỏ 64Bit). Dữ liệu thật nằm trên Heap.

2. Rc<T> - Đa thê, Đa chủ (Reference Counted)

Bạn học Bùa Ownership ở bài 4: 1 Data chỉ có 1 Chủ. Nhưng nếu trong App Game, Bạn vẽ 1 Chiếc Xe, và 2 Màn Hình Giao Diện đều muốn “Làm Cố Chủ” Lấy Cổ Phần Thằng Xe đó?

Dùng Rc<T> (Bộ Đếm Lượt Gọi).

use std::rc::Rc;

fn main() {
    let xe_hoi = Rc::new(String::from("Audi R8"));
    
    // Phân Thân Biến nhưng KHÔNG TỐN THÊM BỘ NHỚ
    let man_hinh_1 = Rc::clone(&xe_hoi); 
    let man_hinh_2 = Rc::clone(&xe_hoi); 

    // Bộ Nhớ xe_hoi giờ báo CÓ TỚI 3 CHỦ (Count = 3)
}

Khi Các màn hình Tắt (Bracket } đóng), Số Count tụt dần về 0. Bằng 0 Phát Lúc Đó Xe Hơi mới bị dọn sọt Rác. Triết Lý Rút Bóng Siêu Việt của Rust thay thế cho Garbage Collector Dỏm. Đoán Rác Từ Gốc!

3. RefCell<T> - Đạo ngụy: Phép Sửa Đồ Bên Trong Lớp Vỏ Đóng Băng

Nếu Bạn Bị Khóa Tay Bằng Lệnh let xe. Bạn Không Thể Gõ xe.push('a') được. Khung Sườn Bất Biến (Immutable). Nhưng Kẹt Một Khía cạch ở Library Người Khác, Họ Bắt Truyền Bất Biến &. Mình Vẫn Bức Tức Muốn Sửa Bí Cẩu Lỗ Trong? Dùng RefCell<T>!

use std::cell::RefCell;

// Vỏ Vách Kính: x được Định Bất Biến!
let x = RefCell::new(5);

// NHƯNG NHỜ BÙA REFCELL, chọc xuyên lớp Kính Thay Số Đục Nghịt:
*x.borrow_mut() = 10;

Rust Chấp Nhận Hạ Phàm Bỏ Đuổi Lọc Bãi Lỗi Compile. Đổi lại Nếu Bạn Gọi Hai Cái Lệnh borrow_mut() Dính chập Nhau Chạy Ở Lúc Chạy Runtime App, App SẼ VỠ Văng NÁT Ngầm PANIC. Sức mạnh luôn Tới Đổi Giá Bọc Lỗi.

Câu hỏi thường gặp (FAQ)

Vậy khi nào nên dùng Box, Rc hay RefCell?

Giữa tâm Bão Mượn Data:

  • Code Bình thường Rút Ruột -> Dùng &&mut.
  • Code Không Thể Biết Định Dạng Lượng Dài To -> Box.
  • Data Có 3 Ông Bà Muốn Nhận Con Tới Cùng Lúc -> Rc.
  • Cần Lừa Trình Compile Ẩn Sửa Trúng Vỏ Lạnh (Mocking Test API) -> RefCell.

Sẵn sàng cho Ngày 18? Nhờ Cơ Chế Quyền Lực Ownership, Trình biên Không Cho Ai Xâm Lấn Nơi Mình Ráp Khớp. Đó Trở Thành Khối Bọc Vàng Phát Triển Công nghệ Multi-threading mà Không Bị Sụp Web Nút Nghẽn Đạt Đỉnh Điểm Tại [Day 18: Sự Cứu Rỗi Concurrency Đa Luồng].

Chuỗi bài viết

30 Ngày Trở Thành Rustacean Tinh Hoa

Phần 17 / 30

30 bài viết
  1. Phần 1 30 Ngày học Rust - Day 1: Lời chào thế giới và Vũ khí Cargo
  2. Phần 2 30 Ngày học Rust - Day 2: Biến, Bất biến (Mutability) và Shadowing
  3. Phần 3 30 Ngày học Rust - Day 3: Luồng điều khiển (Control Flow) và sức mạnh của Match
  4. Phần 4 30 Ngày học Rust - Day 4: Ownership - Khái niệm định hình cỗ thần khí Rust
  5. Phần 5 30 Ngày học Rust - Day 5: Khóa học nhặt đồ chung với References & Borrowing
  6. Phần 6 30 Ngày học Rust - Day 6: Đắp nặn dự án với Structs và Methods
  7. Phần 7 30 Ngày học Rust - Day 7: Quyền năng vô song của Enums và Pattern Matching
  8. Phần 8 30 Ngày học Rust - Day 8: Quản lý dự án với Packages, Crates và Modules
  9. Phần 9 30 Ngày học Rust - Day 9: Các bộ sưu tập chung (Vectors, Strings, Hash Maps)
  10. Phần 10 30 Ngày học Rust - Day 10: Trị dứt điểm Ác mộng Lỗi (Error Handling)
  11. Phần 11 30 Ngày học Rust - Day 11: Generics - Ma thuật Đa hình kiểu dữ liệu
  12. Phần 12 30 Ngày học Rust - Day 12: Traits - Kẻ ban phát quyền năng và Lập pháp Hành vi
  13. Phần 13 30 Ngày học Rust - Day 13: Vượt qua Boss cuối 'Lifetimes' - Sinh Mệnh Biến
  14. Phần 14 30 Ngày học Rust - Day 14: Tận diệt Bug từ trứng nước bằng Automated Tests
  15. Phần 15 30 Ngày học Rust - Day 15: Thực chiến Build Command Line App (CLI) đầu đời
  16. Phần 16 30 Ngày học Rust - Day 16: Functional Magic chốn trần gian (Closures & Iterators)
  17. Phần 17 30 Ngày học Rust - Day 17: Quyền năng của Smart Pointers
  18. Phần 18 30 Ngày học Rust - Day 18: Chinh phục Da luồng (Concurrency) - Cú đâm quyết định của Rust
  19. Phần 19 30 Ngày học Rust - Day 19: Tranh cãi Lập trình hướng đối tượng (OOP) trong Rust
  20. Phần 20 30 Ngày học Rust - Day 20: Mổ xẻ nghệ thuật Advanced Pattern Matching
  21. Phần 21 30 Ngày học Rust - Day 21: Sức mạnh tối thượng của Advanced Traits
  22. Phần 22 30 Ngày học Rust - Day 22: Về Phe Bóng Tối với Unsafe Rust
  23. Phần 23 30 Ngày học Rust - Day 23: Quyền năng của Đấng Tạo Hóa (Declarative Macros)
  24. Phần 24 30 Ngày học Rust - Day 24: Siêu Năng Lực Procedural Macros (Macro Thủ Tục)
  25. Phần 25 30 Ngày học Rust - Day 25: Xây dựng TCP Web Server Đa Luồng (Phần 1: Lõi Socket)
  26. Phần 26 30 Ngày học Rust - Day 26: Xây dựng TCP Web Server Đa Luồng (Phần 2: Bắn trả File HTML)
  27. Phần 27 30 Ngày học Rust - Day 27: Xây dựng TCP Web Server Đa Luồng (Phần 3: The Thread Pool)
  28. Phần 28 30 Ngày học Rust - Day 28: Xây dựng TCP Web Server Đa Luồng (Phần 4: Graceful Shutdown)
  29. Phần 29 30 Ngày học Rust - Day 29: Lên đỉnh Web Server Thực Chiến với Axum và Tokio
  30. Phần 30 30 Ngày học Rust - Day 30: Vượt Vọng Vàng - Đúc Kết Hành Trình Rustacean Tinh Hoa

Bình luận

Quay lại Blog

Bài viết liên quan

Xem tất cả bài viết »