Rust: Result 처리

  • Rust 사용하면서 필수적인 Result 에 대해 정리하며, Result 처리 하는 방법에 대해 코드를 작성합니다.
  • 주의 : 공부하는 과정에서 정리한 문서이므로 부정확할 수 있으며, 수시로 내용 업데이트합니다.

Result 열거형

  • 참고 : Result와 함께하는 복구 가능한 에러
  • 지난 Option 처리 에서 해본
    Option 열거형은 Some 과 None으로 구성되는데,
    Result 열거형은 Ok 와 Err 로 구성됩니다.
  • 동일하게 열거형이므로 match, unwrap/expect, if let 모두 동일하게 동작합니다.
    unwrap/expect 는 역시 panic을 일으키므로 사용시 주의가 필요합니다.
  • 이 장에서 설명하려는 에러 전파 숏컷 ? 는 아래에서 설명합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
fn match_result_1(result: Result<i32, bool>) -> bool {
match result {
Ok(val) => {
if val == 1 {
return true;
} else {
return false;
}
}
Err(b) => return false,
};
}

fn unwrap_result_1(result: Result<i32, bool>) -> bool {
let val = result.unwrap();
if val == 1 {
return true;
} else {
return false;
}
}

fn if_let_result_1(result: Result<i32, bool>) -> bool {
if let Ok(1) = result {
return true;
} else {
return false;
}
}


#[cfg(test)]
mod test {
use super::*;

#[test]
fn test_match_result_1() {
assert!(match_result_1(Ok(1)));
assert!(!match_result_1(Ok(2)));
assert!(!match_result_1(Err(true)));
assert!(!match_result_1(Err(false)));
}
#[test]
fn test_unwrap_result_1() {
assert!(unwrap_result_1(Ok(1)));
assert!(!unwrap_result_1(Ok(2)));
assert!(!unwrap_result_1(Err(true)));
assert!(!unwrap_result_1(Err(false)));
}
#[test]
fn test_if_let_result_1() {
assert!(if_let_result_1(Ok(1)));
assert!(!if_let_result_1(Ok(2)));
assert!(!if_let_result_1(Err(true)));
assert!(!if_let_result_1(Err(false)));
}
}

에러 전파 숏컷 ?

  • 참고 : 에러를 전파하기 위한 숏컷: ?
  • ? 숏컷은 Result 에 대해서만 사용할 수 있습니다.
  • 편리한만큼 명확하게 알지 못하고 건너가면 낭패를 볼 수 있습니다.
    ? 숏컷을 사용할때 Result 의 Err형을 제대로 선언하지 않으면
    컴파일 에러는 계속 발생하고 어떻게 해결해야할지 모르는 상황이 발생하죠.
    (제가 그렇습니다.)
1
2
3
4
5
6
let f = File::open("hello.txt");

let mut f = match f {
Ok(file) => file,
Err(e) => return Err(e),
};
1
let mut f = File::open("hello.txt")?;
  • 위의 두 코드는 동일합니다. match에서 에러일 경우 Err(e) 를 리턴하고 있죠.
    그래서 ?를 사용할때는 Result 의 Err 타입에 대해서 명확하게 알고 작성해야합니다.
1
2
fn read_username_from_file() -> Result<String, io::Error> {
}
  • 위의 두 코드 모두 함수 리턴이 io::Error 로 선언해서 전파해야합니다.
    File::open 의 Result 를 알아야겠네요.
1
pub fn open<P: AsRef<Path>>(path: P) -> Result<File>
  • 참조 : std::io::File::open
    읭? Result 입니다. 이게 뭐지.. 왜 Result<File, io:Error> 이 아니죠?
    링크의 Result를 클릭해보니..
1
2
Type Definition std::io::Result
pub type Result<T> = Result<T, Error>;
  • 그냥 Result가 아니라 std::io::Result 네요..
    Rust 를 배우는 입장에서 정말 이런거 하나때문에 헤메는거 생각하면 너무 힘드네요.
    아무튼 하나 더 알게 되었습니다.
Share