Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Lesson 3 — Working with Structs, Enums, and Pattern Matching


🎯 Learning Objectives

  • Nắm vững cách định nghĩa structenum trong Rust.
  • Hiểu cơ chế pattern matching với match, if let, while let.
  • Biết áp dụng pattern để destructure dữ liệu, quản lý state và xử lý Result/Option.

🔑 Key Concepts & Glossary

Structs

  • Struct gom nhiều field thành một kiểu dữ liệu.
  • Có 3 dạng: Named struct, Tuple struct, Unit struct.

Enums

  • Enum cho phép một giá trị là một trong nhiều biến thể (variant).
  • Mỗi variant có thể chứa dữ liệu khác nhau.

Pattern Matching

  • match là exhaustive (bắt buộc cover hết trường hợp).
  • if let/while let khi chỉ quan tâm một pattern cụ thể.
  • Có thể destructure enum, struct, tuple, slice trực tiếp trong pattern.

Các thuật ngữ quan trọng:

  • Destructuring: Bóc tách giá trị trong pattern.
  • Wildcard (_): Bỏ qua giá trị không quan tâm.
  • ..: Bỏ qua các field còn lại.
  • Exhaustiveness check: Compiler buộc match phải xử lý hết các case có thể.

💻 Example Implementation

Cargo.toml

[package]
name = "lesson03_struct_enum_match"
version = "0.1.0"
edition = "2024"

src/main.rs


#[derive(Debug)]
struct Credential {
    username: String,
    password: String,
}

enum AuthResult {
    Success { user: String },
    Failure(String),
    Locked,
}

fn authenticate(cred: Credential) -> AuthResult {
    if cred.username == "admin" && cred.password == "1234" {
        AuthResult::Success { user: cred.username }
    } else if cred.username == "root" {
        AuthResult::Locked
    } else {
        AuthResult::Failure(format!("Invalid credentials for {}", cred.username))
    }
}

fn main() {
    let creds = vec![
        Credential { username: "admin".into(), password: "1234".into() },
        Credential { username: "alice".into(), password: "wrong".into() },
        Credential { username: "root".into(), password: "toor".into() },
    ];

    for cred in creds {
        match authenticate(cred) {
            AuthResult::Success { user } => println!("✅ Welcome, {user}!"),
            AuthResult::Failure(msg) => println!("❌ {msg}"),
            AuthResult::Locked => println!("🚫 Account is locked"),
        }
    }
}

🛠️ Hands-on Exercises

  1. Struct Exercise Tạo struct Packet { src: String, dst: String, payload: Vec<u8> } → Viết hàm in ra src -> dst (size = n bytes).

  2. Enum Exercise Định nghĩa enum LogLevel { Info, Warning, Error(String) } → Viết hàm log(level: LogLevel) in log phù hợp.

  3. Pattern Matching Challenge Tạo struct Packet { src: String, dst: String, payload: Vec<u8>, port: String }. → Viết hàm parse_port và dùng let-else/if-let để xử lý.


🐞 Common Pitfalls & Debugging Tips

Common Pitfalls

  • Quên cover hết branch trong match → compiler báo lỗi.
  • Lạm dụng _ trong match → có thể bỏ sót bug logic.
  • Dùng enum mà không derive trait (Debug, Clone, Eq, …) → khó debug/log.

🔄 Migration Notes (Rust 2024+)

Migration Guidance

  • Không có breaking change cho struct/enum.
  • Rust 2024 cải thiện ergonomic: destructuring trong let-else và closure tiện hơn.
  • if let/while let pattern binding ngày càng phổ biến, thay thế match dài dòng.

❓ Q&A — Common Questions

Q1. Khi nào dùng struct, khi nào dùng enum?

  • Struct: gom nhiều field cố định.
  • Enum: biểu diễn nhiều trạng thái khác nhau, mỗi trạng thái có thể chứa dữ liệu riêng.

Q2. Khi nào dùng match, khi nào if let?

  • match: khi cần cover hết các trường hợp.
  • if let: khi chỉ quan tâm một case.

Q3. _.. trong pattern nghĩa là gì?

  • _: bỏ qua giá trị không quan tâm.
  • ..: bỏ qua các field còn lại (struct/tuple/slice).

📚 References


🌿 Wisdom Note

Đạo Đức Kinh — Chương 2

Hữu vô tương sinh, nan dị tương thành. (Being and non-being give birth to each other; difficulty and ease complete each other.)

Struct và enum cũng vậy: struct cho hình hài, enum cho trạng thái. Kết hợp với pattern matching, bạn có thể diễn đạt logic an toàn và rõ ràng như chính Đạo.