Biến trong Rust
Một biến (variable) đơn giản là một cái tên bạn đặt cho một giá trị để dùng lại sau này. Hãy hình dung nó như một chiếc hộp có dán nhãn: bạn bỏ một thứ vào hộp, viết tên lên nhãn, rồi gọi nó bằng cái tên đó thay vì lặp lại giá trị ở khắp nơi.
Tạo một biến
Phần tiêu đề “Tạo một biến”Trong Rust, bạn tạo biến bằng từ khóa let:
fn main() { let age = 30; println!("Tôi năm nay {age} tuổi");}Kết quả:
Tôi năm nay 30 tuổiHãy tách dòng đó ra:
let— nói với Rust “tôi đang tạo một biến mới.”age— cái tên chúng ta chọn.=— gán giá trị bên phải cho cái tên bên trái.30— giá trị chúng ta lưu.
{age} bên trong println! in ra giá trị của biến. Cách này gọi là nội suy chuỗi (string interpolation) — Rust thay {age} bằng bất cứ giá trị nào age đang giữ.
Rust tự tìm ra kiểu cho bạn
Phần tiêu đề “Rust tự tìm ra kiểu cho bạn”Mọi giá trị trong Rust đều có một kiểu (type): số nguyên, văn bản, true/false, v.v. Có thể bạn nghĩ phải khai báo kiểu đó, nhưng thường thì không cần — Rust nhìn vào giá trị và tự suy ra. Điều này gọi là suy luận kiểu (type inference).
fn main() { let score = 95; // Rust suy ra đây là số nguyên let name = "Ferris"; // Rust suy ra đây là văn bản let is_active = true; // Rust suy ra đây là boolean println!("{name}: {score}, đang hoạt động = {is_active}");}Kết quả:
Ferris: 95, đang hoạt động = trueNếu muốn viết rõ ràng, bạn có thể ghi kiểu sau dấu hai chấm. Cách này gọi là chú thích kiểu (type annotation):
let score: i32 = 95; // i32 = số nguyên 32 bitMặc định, biến là bất biến
Phần tiêu đề “Mặc định, biến là bất biến”Đây là phần khiến những ai đến từ ngôn ngữ khác bất ngờ: trong Rust, một khi đã gán giá trị cho biến, mặc định bạn không thể thay đổi nó. “Bất biến” (immutable) đơn giản là không thể thay đổi.
Đoạn code này sẽ không biên dịch được:
fn main() { let count = 1; count = 2; // ❌ lỗi: không thể gán hai lần cho biến bất biến println!("{count}");}Trình biên dịch chặn bạn lại với một thông báo rõ ràng (bằng tiếng Anh):
error[E0384]: cannot assign twice to immutable variable `count`Thông báo này nghĩa là “không thể gán hai lần cho biến bất biến count”. Vì sao một ngôn ngữ lại cố tình làm vậy? Vì rất nhiều lỗi đến từ việc giá trị thay đổi khi bạn không ngờ tới. Bằng cách khiến mọi thứ không thể thay đổi trừ khi bạn yêu cầu, Rust giúp code của bạn dễ đoán hơn. Đó là một tính năng, không phải một hạn chế.
Cho phép biến thay đổi với mut
Phần tiêu đề “Cho phép biến thay đổi với mut”Khi bạn thực sự cần một giá trị thay đổi, hãy thêm từ khóa mut (viết tắt của mutable = khả biến, có thể thay đổi):
fn main() { let mut count = 1; println!("Trước: {count}");
count = 2; // ✅ giờ thì được phép, nhờ có `mut` println!("Sau: {count}");}Kết quả:
Trước: 1Sau: 2Shadowing: dùng lại cùng một tên
Phần tiêu đề “Shadowing: dùng lại cùng một tên”Rust cho phép bạn khai báo một biến mới trùng tên với biến cũ. Điều này gọi là shadowing (che khuất) — biến mới “phủ bóng” lên biến cũ:
fn main() { let x = 5; let x = x + 1; // một x mới, dựa trên x cũ -> 6 let x = x * 2; // lại một x mới nữa -> 12 println!("x bằng {x}");}Kết quả:
x bằng 12Trông thì giống mut, nhưng thực ra khác:
mutthay đổi giá trị của cùng một biến.- Shadowing tạo ra một biến hoàn toàn mới chỉ là dùng lại cái tên — và nó thậm chí có thể có kiểu khác.
Shadowing rất tiện khi bạn muốn biến đổi một giá trị nhưng vẫn giữ nguyên tên:
fn main() { let spaces = " "; // văn bản let spaces = spaces.len(); // giờ là một con số (có bao nhiêu dấu cách) println!("Số dấu cách: {spaces}");}Kết quả:
Số dấu cách: 3Hằng số
Phần tiêu đề “Hằng số”Một hằng số (constant) là một giá trị không bao giờ thay đổi và được cố định ngay lúc biên dịch. Bạn khai báo nó bằng const thay vì let, và bạn bắt buộc phải ghi kiểu:
const MAX_SCORE: u32 = 100;
fn main() { println!("Điểm tối đa là {MAX_SCORE}");}Kết quả:
Điểm tối đa là 100Theo quy ước, hằng số được viết bằng UPPER_SNAKE_CASE. Đây là cách chúng so với biến thông thường:
Biến let |
Hằng số const |
|
|---|---|---|
| Có thể thay đổi? | Chỉ khi có mut |
Không bao giờ |
| Bắt buộc ghi kiểu? | Không bắt buộc (được suy luận) | Bắt buộc |
| Kiểu đặt tên | snake_case |
UPPER_SNAKE_CASE |
| Được đặt ở đâu | Bên trong hàm | Bất cứ đâu, kể cả bên ngoài hàm |
Hãy dùng hằng số cho những giá trị thực sự cố định — như số giây trong một phút, hay một giới hạn tối đa.
Quy tắc đặt tên
Phần tiêu đề “Quy tắc đặt tên”- Dùng
snake_case— các từ viết thường nối với nhau bằng dấu gạch dưới:user_name,total_price. - Tên có thể chứa chữ cái, chữ số và dấu gạch dưới, nhưng không được bắt đầu bằng chữ số.
- Chọn tên có ý nghĩa:
agetốt hơna.
Luyện tập
Phần tiêu đề “Luyện tập”1. Lên cấp
Phần tiêu đề “1. Lên cấp”Tạo một biến level bắt đầu từ 1. In nó ra, tăng nó lên 1 hai lần, và in sau mỗi lần thay đổi, để bạn có Cấp 1, Cấp 2, Cấp 3. Gợi ý: một giá trị thay đổi cần có mut, và level = level + 1; cộng thêm một.
Xem lời giải
fn main() { let mut level = 1; println!("Cấp {level}");
level = level + 1; println!("Cấp {level}");
level = level + 1; println!("Cấp {level}");}Kết quả:
Cấp 1Cấp 2Cấp 32. Đổi phút ra giây
Phần tiêu đề “2. Đổi phút ra giây”Khai báo một hằng số SECONDS_PER_MINUTE bằng 60. Bắt đầu với let time = 5; (tính bằng phút), rồi shadow time để nó giữ cùng khoảng thời gian đó nhưng tính bằng giây, và in ra Tức là 300 giây. Gợi ý: time mới có thể được tạo từ time cũ: let time = time * ...;.
Xem lời giải
const SECONDS_PER_MINUTE: u32 = 60;
fn main() { let time = 5; // phút let time = time * SECONDS_PER_MINUTE; // một `time` mới, giờ tính bằng giây println!("Tức là {time} giây");}Kết quả:
Tức là 300 giâyKhông cần mut: let thứ hai tạo ra một biến hoàn toàn mới dùng lại cái tên cũ. Rust còn suy ra time ở đây là u32, vì nó được nhân với hằng số kiểu u32.
Tóm tắt
Phần tiêu đề “Tóm tắt”- Tạo biến bằng
let; Rust thường tự suy luận kiểu cho bạn. - Mặc định biến là bất biến — thêm
mutđể cho phép thay đổi. - Shadowing khai báo lại một tên bằng
let, tạo ra một biến mới (có thể đổi kiểu). - Hằng số (
const) không bao giờ thay đổi, luôn cần ghi kiểu, và dùngUPPER_SNAKE_CASE.
Kiểm tra nhanh
Phần tiêu đề “Kiểm tra nhanh”Kiểm tra nhanh
1. Mặc định, bạn có thể gán lại giá trị cho một biến let trong Rust không?
2. Shadowing trong Rust là gì?
3. Theo trang này, biến trong Rust dùng quy ước đặt tên nào?
Điểm: 0 / 3
Đọc thêm
Phần tiêu đề “Đọc thêm”- Variables and Mutability — The Rust Book (tiếng Anh): chương chính thức về
let,mut, hằng số và vì sao bất biến là mặc định. - Shadowing — The Rust Book (tiếng Anh): thêm về chỗ shadowing khác
mut, kể cả việc đổi kiểu của một giá trị. - Variable Bindings — Rust by Example (tiếng Anh): ví dụ ngắn chạy được, kèm các phần tiếp theo về tính khả biến và phạm vi và shadowing.
- Constants — Rust by Example (tiếng Anh):
const(và người anh emstatic) trong một chương trình nhỏ. letkeyword — standard library docs (tiếng Anh): mọi thứletlàm được, cho lúc bạn muốn có bức tranh đầy đủ.