1. Result & Option
use std::fs;
use std::num::ParseIntError;
fn main() {
// Option<T> — có hoặc không
let value: Option<i32> = Some(42);
let nothing: Option<i32> = None;
// Unwrap — PROD không nên dùng
let v = value.unwrap(); // panic nếu None
let v = value.expect("No value"); // panic với message
// Safe access
let v = value.unwrap_or(0);
let v = value.unwrap_or_else(|| compute_default());
let v = value.map(|x| x * 2); // Some(84)
// Result<T, E> — success hoặc error
let content: Result<String, std::io::Error> = fs::read_to_string("config.toml");
match content {
Ok(text) => println!("{}", text),
Err(e) => eprintln!("Error: {}", e),
}
}
2. ? Operator & Error Propagation
use std::io;
fn read_config() -> Result<Config, AppError> {
let content = fs::read_to_string("config.toml")?; // Auto-convert io::Error → AppError
let port: u16 = content.trim().parse()?; // Auto-convert ParseIntError → AppError
Ok(Config { port })
}
// ? hoạt động nhờ From trait
// impl From<io::Error> for AppError { ... }
// impl From<ParseIntError> for AppError { ... }
3. Custom Errors với thiserror & anyhow
// thiserror — cho library code
use thiserror::Error;
#[derive(Error, Debug)]
enum AppError {
#[error("Database error: {0}")]
Database(#[from] sqlx::Error),
#[error("Not found: {entity} with id {id}")]
NotFound { entity: String, id: String },
#[error("Unauthorized")]
Unauthorized,
#[error("Validation error: {0}")]
Validation(String),
#[error(transparent)]
Other(#[from] anyhow::Error),
}
// anyhow — cho application code
use anyhow::{Context, Result};
async fn setup_database() -> Result<Pool<Postgres>> {
let url = std::env::var("DATABASE_URL")
.context("DATABASE_URL must be set")?;
let pool = PgPoolOptions::new()
.max_connections(5)
.connect(&url)
.await
.context("Failed to connect to database")?;
Ok(pool)
}
4. Module System
src/
├── main.rs
├── lib.rs
├── config.rs
├── models/
│ ├── mod.rs
│ ├── user.rs
│ └── product.rs
└── handlers/
├── mod.rs
└── auth.rs
// src/models/mod.rs
pub mod user;
pub mod product;
// src/models/user.rs
pub struct User {
pub id: u64,
pub username: String,
email: String, // private
}
impl User {
pub fn new(id: u64, username: String, email: String) -> Self {
Self { id, username, email }
}
}
// src/main.rs
mod config;
mod models;
mod handlers;
use models::user::User;
# Cargo workspace — multiple crates
# Cargo.toml (root)
[workspace]
members = ["api", "domain", "infrastructure"]
# api/Cargo.toml
[dependencies]
domain = { path = "../domain" }
infrastructure = { path = "../infrastructure" }
Bài tiếp theo: Smart Pointers & Concurrency.