Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

에러 Box하기

원본 에러를 보존하면서 단순한 코드를 작성하는 방법은 에러들을 Box하는 것입니다. 단점은 기저 에러 타입을 런타임에만 알 수 있고 정적으로 결정되지 않는다는 것입니다.

표준 라이브러리는 BoxFrom을 통해 Error 트레이트를 구현하는 모든 타입으로부터 트레이트 객체 Box<Error>로의 변환을 구현하도록 함으로써 에러를 박싱하는 것을 돕습니다.

use std::error;
use std::fmt;

// 별칭이 `Box<dyn error::Error>`를 사용하도록 변경합니다.
type Result<T> = std::result::Result<T, Box<dyn error::Error>>;

#[derive(Debug, Clone)]
struct EmptyVec;

impl fmt::Display for EmptyVec {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "두 배로 만들 첫 번째 항목이 유효하지 않습니다")
    }
}

impl error::Error for EmptyVec {}

fn double_first(vec: Vec<&str>) -> Result<i32> {
    vec.first()
        .ok_or_else(|| EmptyVec.into()) // Into 트레이트를 사용하여 Box로 변환합니다.
        .and_then(|s| {
            s.parse::<i32>()
                .map_err(From::from) // From::from 함수 포인터를 사용하여 Box로 변환합니다.
                .map(|i| 2 * i)
        })
}

fn print(result: Result<i32>) {
    match result {
        Ok(n) => println!("두 배가 된 첫 번째 값은 {}입니다", n),
        Err(e) => println!("에러: {}", e),
    }
}

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

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

참고:

동적 디스패치(Dynamic dispatch)Error 트레이트