Rust 의 Result 타입 탐구

Beginner

This tutorial is from open-source community. Access the source code

소개

이 랩에서는 Rust 의 Result 타입을 살펴봅니다. Result 타입은 Option 타입처럼 값의 부재 가능성이 아닌 잠재적인 오류를 처리하는 방법을 제공합니다. Result 타입은 두 가지 결과를 가질 수 있습니다. 성공적인 결과와 요소 T를 나타내는 Ok(T)와, 오류와 요소 E를 나타내는 Err(E)입니다. 코드 예제에서 Result를 사용하는 방법과, 오류를 처리하고 더 구체적인 오류 메시지를 제공하기 위해 main 함수의 반환 타입으로 사용하는 방법을 살펴보겠습니다.

참고: 랩에서 파일 이름을 지정하지 않은 경우, 원하는 파일 이름을 사용할 수 있습니다. 예를 들어, main.rs를 사용하고, rustc main.rs && ./main으로 컴파일하고 실행할 수 있습니다.

Result

Result는 가능한 부재 대신 가능한 오류를 설명하는 Option 타입의 더 풍부한 버전입니다.

즉, Result<T, E>는 두 가지 결과 중 하나를 가질 수 있습니다.

  • Ok(T): 요소 T가 발견되었습니다.
  • Err(E): 요소 E와 함께 오류가 발견되었습니다.

관례적으로, 예상되는 결과는 Ok이고 예상치 못한 결과는 Err입니다.

Option과 마찬가지로, Result는 많은 관련 메서드를 가지고 있습니다. 예를 들어, unwrap()는 요소 T를 반환하거나 panic을 발생시킵니다. 케이스 처리를 위해, ResultOption 사이에 중복되는 많은 컴비네이터 (combinator) 가 있습니다.

Rust 를 사용하면서, parse() 메서드와 같이 Result 타입을 반환하는 메서드를 접하게 될 것입니다. 문자열을 다른 타입으로 파싱 (parsing) 하는 것이 항상 가능하지 않으므로, parse()는 실패 가능성을 나타내는 Result를 반환합니다.

문자열을 성공적으로 그리고 실패적으로 parse()하는 경우 어떻게 되는지 살펴보겠습니다.

fn multiply(first_number_str: &str, second_number_str: &str) -> i32 {
    // Let's try using `unwrap()` to get the number out. Will it bite us?
    let first_number = first_number_str.parse::<i32>().unwrap();
    let second_number = second_number_str.parse::<i32>().unwrap();
    first_number * second_number
}

fn main() {
    let twenty = multiply("10", "2");
    println!("double is {}", twenty);

    let tt = multiply("t", "2");
    println!("double is {}", tt);
}

실패한 경우, parse()unwrap()panic을 발생시킬 오류를 남깁니다. 또한, panic은 프로그램을 종료하고 불쾌한 오류 메시지를 제공합니다.

오류 메시지의 품질을 향상시키기 위해, 반환 타입에 대해 더 구체적으로 설명하고 오류를 명시적으로 처리하는 것을 고려해야 합니다.

main에서 Result 사용하기

Result 타입은 명시적으로 지정된 경우 main 함수의 반환 타입이 될 수도 있습니다. 일반적으로 main 함수는 다음과 같은 형태를 가집니다.

fn main() {
    println!("Hello World!");
}

그러나 mainResult의 반환 타입을 가질 수도 있습니다. main 함수 내에서 오류가 발생하면 오류 코드를 반환하고 오류의 디버그 표현 ([Debug] 트레이트를 사용하여) 을 출력합니다. 다음 예제는 이러한 시나리오를 보여주고 [다음 섹션]에서 다루는 측면에 대해 언급합니다.

use std::num::ParseIntError;

fn main() -> Result<(), ParseIntError> {
    let number_str = "10";
    let number = match number_str.parse::<i32>() {
        Ok(number)  => number,
        Err(e) => return Err(e),
    };
    println!("{}", number);
    Ok(())
}

요약

축하합니다! Result 랩을 완료했습니다. LabEx 에서 더 많은 랩을 연습하여 실력을 향상시킬 수 있습니다.