🔲
RustのResult型とOption型のエラーチェックがコードレビュー後にスッキリした話
初期実装(unwrapで例外を処理していないので非推奨)
let cookie_data: Option<&MetadataValue<Ascii>> = request.metadata().get("cookie");
if cookie_data.is_none() {
return Err("cookieがありません");
}
let cookie: &str = cookie_data.unwrap().to_str().unwrap();
println!("{}", cookie);
unwrap無しにした版
let cookie_data: Option<&MetadataValue<Ascii>> = request.metadata().get("cookie");
let cookie: &str = match cookie_data {
Some(cookie) => cookie.to_str().map_err(|_| {
Err("cookieが不正です")
})?,
None => {
return Err("cookieがありません")
}
};
println!("{}", cookie);
最終版
let cookie_data = request.metadata().get("cookie");
// cookie情報を取得する
let cookie: &str = cookie_data // Option<&MetadataValue<Ascii>>
.ok_or_else(|| Err("cookieがありません"))?
.to_str() // Result<&str, ToStrError>
.map_err(|_| Err("cookieが不正です"))?;
println!("{}", cookie);
Option型の場合は、.ok_or_else
Result型の場合は、.map_err
を使っている。
Result型とOption型で、ハンドリング方法は揃えてくれたらいいのにと思った。
余談
fn main() {
let value: Option<usize> = Some(1);
let result = value.ok_or({ println!("出力される"); 0 }); // output 出力される
println!("{}", result.unwrap()); // output 1
let result = value.ok_or_else(|| { println!("出力されない"); 0 });
println!("{}", result.unwrap()); // output 1
}
ok_or と ok_or_else は、基本同じ動作となるが ok_or のほうは直感に反する動きをするので、ok_or_else 推奨となる。
所感
最終版はスッキリとしたなと。
Discussion