16.5 Defining an error type

Rust는 우리 고유의 에러 타입을 정의할 수 있게 허용한다 일반적으로 "좋은" 에러 타입은:

  • 서로 다른 에러를 같은 타입으로 표현
  • 사용자에게 좋은 에러 메시지를 출력
  • 다른 타입들과의 쉬운 비교
    • Good: Err(EmptyVec)
    • Bad: Err("Please use a vector with at least one element".to_owned())
  • 에러에 대한 정보를 보관
    • Good: Err(BadChar(c, position))
    • Bad: Err("+ cannot be used here".to_owned())

주목할 점은 String(아직까지 사용되고 있는)이 첫 두 항목을 만족하지만, 마지막 둘은 아니라는 점이다. 이는 String 에러가 장황하고 반응하기 어렵게 만든다. 이는 필요 없이 String을 보기 좋게 형식화하는 것과 관련된 무거운 코드가 로직을 오염시킨다.

use std::num::ParseIntError;
use std::fmt;

type Result<T> = std::result::Result<T, DoubleError>;

#[derive(Debug)]
// 오류 타입들을 정의한다. 우리의 에러 처리를 위해 사용자 정의될 수 있다.
// 이제 우리 자신의 오류를 작성하거나, 기본 오류 구현을 연기하거나,
// 중간에 뭔가 할 수 있다. 
enum DoubleError {
    // 이 오류를 자세히 설명하기 위해 추가 정보가 필요하지 않다.
    EmptyVec,
    // 우리는 분석 오류에 대한 구현을 연기할 것이다. 
    // 추가 정보를 제공하려면 타입에 데이터를 더 추가해야 한다.
    Parse(ParseIntError),
}

// 에러의 생성은 표시하는 방법과는 완전히 별개이다.
// 표시하는 스타일을 위한 복잡한 로직으로 혼란스럽게 되는 것을 걱정할 필요가 없다.
//
// 에러에 대한 추가 정보는 저장하지 않는다. 이는 정보를 전달하기 위해 
// 우리의 타입을 수정하지 않고 분석에 실패한 문자열을 말할 수 없음을 뜻한다.
impl fmt::Display for DoubleError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            DoubleError::EmptyVec =>
                write!(f, "please use a vector with at least one element"),
            // 이는 래퍼로 `fmt`구현의 타입에 종속된다. 
            DoubleError::Parse(ref e) => e.fmt(f),
        }
    }
}

fn double_first(vec: Vec<&str>) -> Result<i32> {
    vec.first()
       // 에러를 우리의 새 타입으로 변경한다.
       .ok_or(DoubleError::EmptyVec)
       .and_then(|s| s.parse::<i32>()
            // 여기도 새 에러 타입으로 업데이트.
            .map_err(DoubleError::Parse)
            .map(|i| 2 * i))
}

fn print(result: Result<i32>) {
    match result {
        Ok(n)  => println!("The first doubled is {}", n),
        Err(e) => println!("Error: {}", e),
    }
}

fn main() {
    let numbers = vec!["93", "18"];
    let empty = vec![];
    let strings = vec!["tofu", "93", "18"];

    print(double_first(numbers));
    print(double_first(empty));
    print(double_first(strings));
}

See also:

Result and io::Result

results matching ""

    No results matching ""