【Rust】エラーハンドリングの基本

実行した時にエラーになりうる関数はResultを返す。
Ok(File), Err(Error)など

1
2
3
4
5
6
7
8
9
10
11
12
13
use std::fs::File;
 
fn main() {
    let result = File::open("file.txt");
    match result {
        Ok(file) => {
            println!("ファイルのオープンに成功しました!");
        }
        Err(error) => {
            println!("ファイルのオープンに失敗しました!");
        }
    }
}

Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.70s
Running `target/debug/app`
ファイルのオープンに失敗しました!

関数化すると

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
use std::fs::File;
 
#[derive(Debug)]
struct MyError {
    message: String,
}
 
fn main() {
    let result = open_file();
    println!("{:?}", result);
}
 
fn open_file() -> Result<File, MyError> {
    let result = File::open("file.txt");
    match result {
        Ok(file) => {
            return Ok(file);
        }
        Err(error) => {
            let error = MyError{ message: "ファイルのオープンに失敗しました!".to_string()};
            return Err(error);
        }
    }
}

Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.30s
Running `target/debug/app`
Err(MyError { message: “ファイルのオープンに失敗しました!” })

### エラーが発生した時、発生したエラーをそのまま返す

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
fn main() {
    let result = open_file();
    println!("{:?}", result);
}
 
fn open_file() -> Result<File, std::io::Error> {
    let result = File::open("file.txt");
    match result {
        Ok(file) => {
            return Ok(file);
        }
        Err(error) => {
            return Err(error);
        }
    }
}

“?”とすれば、その時点でエラーを返す。下記の方が簡略して書ける。

1
2
3
4
5
6
7
8
9
10
fn main() {
    let result = open_file();
    println!("{:?}", result);
}
 
fn open_file() -> Result<(), std::io::Error> {
    let result = File::open("file.txt");
    let file = result?;
    Ok(())
}

File::open(SCHEDULE_FILE).unwrap()のunwrap()はエラーだたった時、エラー内容を表示してそのまま終了してしまう。
Result<(), std::io::Error> と書いた場合は、エラーだったときに、終了せずにエラーを返す。