Pelajaran modul (2/2)
Penanganan Kesalahan dan ? Operator
Filosofi Rust mendorong Anda untuk mengenali kemungkinan kesalahan secara eksplisit dan menyusun kode Anda untuk menanganinya sebelum program dikompilasi.
Kesalahan di Rust dibagi menjadi dua kategori utama: kesalahan yang tidak dapat dipulihkan (yang menyebabkan penghentian langsung melalui makro panic!) dan kesalahan yang dapat dipulihkan (dikelola menggunakan tipe Result<T, E>).
Hasil<T,E> Pencocokan Jenis dan Pola
Sebagian besar kesalahan yang dapat dipulihkan mengembalikan tipe Result<T, E>, yang merupakan enum yang didefinisikan sebagai:
enum Result<T, E> {
Ok(T),
Err(E),
}Kita dapat menggunakan pencocokan pola untuk memeriksa hasilnya:
use std::fs::File;
fn main() {
let greeting_file_result = File::open("hello.txt");
let greeting_file = match greeting_file_result {
Ok(file) => file,
Err(error) => panic!("Problem opening the file: {:?}", error),
};
}Propagasi Kesalahan dengan Operator ?
Saat mengimplementasikan suatu fungsi, alih-alih menangani kesalahan secara langsung di dalamnya, kita sering kali ingin mengembalikan kesalahan tersebut kepada pemanggil sehingga mereka dapat memutuskan apa yang harus dilakukan. Proses ini disebut propagasi kesalahan.
Rust menyediakan operator ? sebagai pintasan sintaksis untuk menyebarkan kesalahan. Jika nilai Result adalah Ok, nilai dalam Ok dikembalikan oleh ekspresi; jika Err, kesalahan Err dikembalikan dari seluruh fungsi saat ini seolah-olah kita telah menggunakan return Err(...).
use std::fs::File;
use std::io::{self, Read};
fn read_username_from_file() -> Result<String, io::Error> {
let mut username_file = File::open("username.txt")?;
let mut username = String::new();
username_file.read_to_string(&mut username)?;
Ok(username)
}[!PENTING] Operator
?hanya dapat digunakan dalam fungsi yang mengembalikan tipe yang kompatibel dengan nilai yang diterapkan (biasanyaResult,Option, atau tipe yang menerapkanFromResidual).
Kesalahan Khusus
Kita dapat menentukan jenis kesalahan khusus kita sendiri dengan menerapkan sifat std::fmt::Display (dan opsional std::error::Error) untuk memberikan representasi kesalahan yang dapat dibaca manusia:
use std::fmt;
#[derive(Debug)]
struct MyError {
details: String,
}
impl fmt::Display for MyError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Error: {}", self.details)
}
}
impl std::error::Error for MyError {}Cobalah sendiri
Latihan 1: Membaca file dengan ? operator
Lengkapi fungsi read_username_from_file sehingga menggunakan ? operator untuk menyebarkan kesalahan yang dihasilkan dengan membuka file dan membaca kontennya ke dalam string nama pengguna.
Tunjukkan petunjuk
Tambahkan `?`karakter setelah`File::open(...)`dan setelah`nama_file.read_to_string(...)` untuk menyebarkan kesalahan.
Solusi tersedia setelah 3 upaya
Latihan 2: Mengurai dan Menggandakan Angka
Tulis fungsi bernama parse_and_double yang menerima referensi string &str dan mengembalikan Hasil<i32, std::num::ParseIntError>. Fungsi tersebut harus mengurai string menggunakan val.parse::<i32>() dengan ? untuk menyebarkan kesalahan penguraian, dan jika berhasil mengembalikan nilai dua kali lipat yang dibungkus dengan Ok.
Tunjukkan petunjuk
Gunakan `val.parse::<i32>()?`untuk mengurai string dan menyebarkan kesalahan, lalu return`Ok(num \* 2)`.
Solusi tersedia setelah 3 upaya
Latihan 3: Mendefinisikan Kesalahan Khusus
Tentukan struktur kosong bernama CustomError. Terapkan sifat std::fmt::Display dengan menulis 'Si e verificato un errore personalizzato' sebagai pesan kesalahan dalam metode fmt.
Tunjukkan petunjuk
Deklarasikan `struct CustomError;`dan implementasikan Tampilan dengan menulis`write!(f, "Si e verificato un errore personalizzato")`di dalam metode `fmt`.
Solusi tersedia setelah 3 upaya