Menangani Result di Rust untuk level Production
Kalau kamu baru belajar Rust, cepat atau lambat kamu akan ketemu fungsi yang hasilnya berupa Result<T, E>
.
Banyak tutorial pemula sering kasih contoh pakai .unwrap()
supaya cepat dapat nilainya, tapi di kode produksi (production code) cara itu berbahaya.
Di artikel ini, kita akan bahas:
Apa sih
Result
itu?Kenapa sebaiknya hindari
unwrap()
?Cara aman dan rapi menangani
Result
denganmatch
atauunwrap_or_else
.Kapan perlu bikin fungsi jadi
async
.
Apa Itu Result<T, E>
?
Result
itu enum bawaan Rust, isinya cuma dua kemungkinan:
enum Result<T, E> {
Ok(T),
Err(E),
}
Kalau kita punya Result<String, String>
artinya:
Ok(String)
→ sukses, isinya nilai yang kita mau (misalnya API key)Err(String)
→ gagal, isinya pesan error
Contoh fungsi sederhana:
fn find_api_key() -> Result<String, String> {
let var_name = "API_KEY";
if let Some(v) = from_env_var(var_name) {
return Ok(v);
}
if let Ok(Some(v)) = from_dotenv_file(".env", var_name) {
return Ok(v);
}
Err("API key tidak ditemukan di ENV atau file .env".to_string())
}
Jadi fungsi ini bisa sukses (Ok(api_key)
) atau gagal (Err("pesan error")
).
Kenapa Jangan Pakai .unwrap()
di Production?
.unwrap()
itu gampang banget dipakai:
let api_key = find_api_key().unwrap();
Tapi hati-hati: kalau hasilnya Err
, program kamu bakal panic dan langsung crash.
Di project serius, ini bikin pengalaman pengguna jelek, dan susah dilacak.
Cara Aman: Pakai match
Cara yang paling aman dan jelas adalah pakai match
.
Dengan match
, kamu harus tangani dua-duanya: Ok
dan Err
.
#[tokio::main]
async fn main() {
let api_key = match find_api_key() {
Ok(api_key) => api_key, // ambil nilai dari Ok(...)
Err(e) => {
eprintln!("Gagal ambil API key: {}", e);
std::process::exit(1); // keluar program dengan kode error
}
};
println!("API key ditemukan: {}", api_key);
// lanjut pakai api_key
}
Kelebihan cara ini:
Jelas: keliatan kita handle sukses dan error.
Aman: compiler maksa kita tangani semua kemungkinan.
Fleksibel: gampang ditambah log, fallback, atau retry di masa depan.
Alternatif Lebih Singkat: unwrap_or_else
Kalau mau lebih singkat tapi tetap aman, bisa pakai unwrap_or_else
:
let api_key = find_api_key().unwrap_or_else(|e| {
eprintln!("Gagal ambil API key: {}", e);
std::process::exit(1);
});
Bagus untuk kasus sederhana, tapi agak susah kalau nanti kita mau tambah logika lebih rumit.
Perlu Bikin async
Nggak?
find_api_key()
di contoh tadi masih fungsi biasa (sync).
Kita cuma baca environment variable dan file .env
, itu cepat dan nggak butuh async.
Kamu baru perlu bikin fungsi jadi async
kalau:
Ada network call (misalnya ambil API key dari server)
Ada operasi file atau database yang non-blocking
Kalau nanti diubah jadi async:
async fn find_api_key() -> Result<String, String> {
// operasi async
}
Panggilnya pakai .await
:
let api_key = match find_api_key().await {
Ok(api_key) => api_key,
Err(e) => {
eprintln!("Error: {}", e);
std::process::exit(1);
}
};
Singkatnya
Jangan pakai
.unwrap()
di Production — program bisa panic.Pakai
match
untuk cara yang jelas dan fleksibel.Pakai
unwrap_or_else
kalau mau singkat tapi tetap aman.Jangan bikin fungsi
async
kalau nggak perlu, supaya kode tetap sederhana.
Dengan cara ini, kode kamu akan lebih rapi, lebih aman, dan lebih siap dipakai di project serius.
Untuk mempelajari pemrograman Rust lebih lengkap bisa belajar di kelas Belajar Pemrograman Rust untuk Pemula di Dicoding.