Error Propagation di Rust
Ketika fungsi bisa gagal, kita perlu cara untuk meneruskan error ke caller. Rust menyediakan operator ? yang membuat error propagation menjadi sangat ergonomis.
Tanpa ? Operator (Manual)
use std::num::ParseIntError;
fn hitung_ganda(s: &str) -> Result<i32, ParseIntError> {
let angka = match s.parse::<i32>() {
Ok(n) => n,
Err(e) => return Err(e), // propagate error
};
Ok(angka * 2)
}
Dengan ? Operator (Idiomatic)
fn hitung_ganda(s: &str) -> Result<i32, ParseIntError> {
let angka = s.parse::<i32>()?; // ? = jika Err, langsung return Err
Ok(angka * 2)
}
// Bahkan lebih singkat:
fn hitung_ganda_v2(s: &str) -> Result<i32, ParseIntError> {
Ok(s.parse::<i32>()? * 2)
}
Chaining dengan ?
fn proses_data(input: &str) -> Result<i32, ParseIntError> {
let step1 = input.trim().parse::<i32>()?;
let step2 = (step1 * 2).to_string().parse::<i32>()?;
Ok(step2 + 10)
}
Custom Error Type
use std::fmt;
#[derive(Debug)]
enum AppError {
ParseError(String),
ValidationError(String),
NotFound(String),
}
impl fmt::Display for AppError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
AppError::ParseError(msg) => write!(f, "Parse error: {}", msg),
AppError::ValidationError(msg) => write!(f, "Validation error: {}", msg),
AppError::NotFound(msg) => write!(f, "Not found: {}", msg),
}
}
}
fn validasi_umur(input: &str) -> Result<u32, AppError> {
let umur: u32 = input.parse()
.map_err(|_| AppError::ParseError("Bukan angka".into()))?;
if umur > 150 {
return Err(AppError::ValidationError("Umur tidak valid".into()));
}
Ok(umur)
}
? dengan Option
fn first_even(v: &[i32]) -> Option<i32> {
let first = v.first()?; // return None jika kosong
if first % 2 == 0 {
Some(*first)
} else {
None
}
}
Best Practices
- Gunakan
Resultuntuk fungsi yang bisa gagal — janganunwrap()di production code - Gunakan
?untuk propagation — lebih bersih daripada match manual - Buat custom error types untuk library/aplikasi besar
- Pertimbangkan crate
thiserror(untuk library) dananyhow(untuk aplikasi) untuk error handling yang lebih ergonomis