- 回復可能なエラー
- ファイルが見つからない など
- [[Result]]で制御
- 回復不能なエラー
- [[配列 (Rust)|配列]]の境界を越えた箇所にアクセス など
- [[panicマクロ]]
## [[panicマクロ|panic!]]で回復不能なエラー
- `RUST_BACKTRACE=1`で[[スタックトレース]]を出せる
## Resultで回復可能なエラー
- [[マッチガード]]
- `Err(ref error) if ...` の `ref` は `error` が[[マッチガード]]にムーブしないためのもの
- `Err(&error) if ...` では参照に対して[[パターンマッチ (Rust)|パターンマッチ]]してしまうため型違いでエラーになる
```rust
use std::fs::File;
use std::io::ErrorKind;
fn main() {
let f = File::open("hoge");
let f = match f {
Ok(file) => file,
Err(ref error) if error.kind() == ErrorKind::NotFound => {
panic!("Not found");
}
_ => {
panic!("Unexpected error");
}
};
eprintln!("f = {:?}", f);
}
```
- `.expect(...)`で`.unwrap()`と同じ動きをしつつ失敗時のエラーメッセージを決定
```rust
fn main() {
let f = File::open("hoge");
let f = f.expect("hogehogehoge not found!!");
}
// thread 'main' panicked at 'hogehogehoge not found!!: Os { code: 2, kind: NotFound, message: "指定されたファイルが見つかりません。" }', src\main.rs:6:15
```
上記は`unwrap`で表示される情報プラスアルファになっている。
```rust
fn main() {
let f = File::open("hoge");
let f = f.unwrap();
}
// thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 2, kind: NotFound, message: "指定されたファイルが見つかりません。" }', src\main.rs:6:15
```
- [[アーム]]の中で`return`を使うと関数の戻り値になる
- [[Question mark operator]]
- エラー型変換の`from`関数を通る
たとえば
- オリジナルのエラーが型 `MyError`は`From<io::Error>`を実装する
- `io:Error`から`MyError`への変換が可能
- `File::open`は`io::Error`を返す
という状況で[[Question mark operator]]を使うと、[[戻り値型]]である`MyError`は`io::Error`を受けて変換できるポテンシャルを秘めているため、このコードはコンパイルが通る。
```rust
use std::fs::File;
use std::io;
use std::io::Error;
struct MyError {}
impl From<io::Error> for MyError {
fn from(_: Error) -> Self {
MyError {}
}
}
fn func() -> Result<File, MyError> {
let r = File::open("hoge")?;
Ok(r)
}
fn main() {
let f = func();
}
```
## panic!すべきかするまいか
- [[Rustでpanicマクロを使うとき、使わないとき]]
- [[構造体 (Rust)|構造体]]の[[インスタンス (Rust)|インスタンス]]生成関数 (`new`) でバリデーションする例
- [[Result]]でなく[[panicマクロ]]使うのね...
- ユーザー入力のときはどっちがいいのかな?
- 自分は[[Result]]使って、そのままそれをUIにも利用してた
- [[panicマクロ]]で落としつつ、UI側でも同じvalidationを書けばいい?
- それって二度手間でメンテ辛いから賛同はしかねる