Archive/Rust

[Rustlings] 11. Error Handling

Rust에는 Error Handling을 할 때 Result라는 타입을 사용한다. ResultOkErr로 나뉘는데, Ok는 과제를 성공적으로 수행했을 때 내보내는 값이고 Err는 과제 수행 중에 발생한 오류를 나타낸다.

enum Result<T, E> {
  Ok(T),
  Err(E),
}

예를 들어 어떤 문자열을 정수로 파싱하는 경우, 성공적으로 정수로 변환할 수 있지만 빈 문자열이나 숫자가 아닌 다른 문자가 포함된 경우에는 정수로 파싱할 수 없다. 그래서 parse 함수는 Result를 반환해 정수 변환에 성공했는지 실패했는지 결과를 넘겨준다.

let num = input.parse::<i32>();

let num = match num {
  Ok(n) => n,
  Err(error) => panic!("Input a valid number."),
};

Result를 반환하는 함수를 호출할 때는 반환값 처리를 위해 자주 match를 사용한다. 그래서 Result는 자주 사용하는 처리 방법을 함수로 제공한다.

만약 위의 코드처럼 Ok를 받으면 그 안의 값을 꺼내고, Err를 받으면 panic을 발생시키려 한다면 unwrap이나 expect를 사용하면 된다.

let num = input.parse::<i32>().unwrap();

// or

let num = input.parse::<i32>().expect("`input` is not vaild.");

만약 작성하고 있는 함수가 에러를 발생할 수 있는 동작을 수행한다면, 보통 함수 내에서 에러 처리를 하지 않고 Result를 반환하도록 함수를 작성한다. 이처럼 호출자에게 Result를 넘겨 호출자가 에러를 처리하는 방식을 propagating errors 라고 한다.

fn read_line_from_file() -> Result<String, io::Error> {
  let mut file = match File::open("input.txt") {
    Ok(file) => file,
    Err(error) = return Err(error),
  };
  
  let mut input = String::new();
  
  match file.read_to_string(&mut input) {
    Ok(_) => Ok(input),
    Err(error) => Err(Error),
  }
}

propagating errors도 자주 보이는 패턴이라 축약 표기가 존재한다. Result를 반환하는 함수 뒤에 ?를 붙이면 된다. 해당 함수가 Ok를 반환하면 그 안의 값을 그대로 넘겨주고 계속 함수를 실행하지만, Err를 받으면 그 Err 자체를 현재 실행되는 함수 자체의 반환값으로 넘긴다.

fn read_line_from_file() -> Result<String, io::Error> {
  let mut file = match File::open("input.txt")?;
  let mut input = String::new();
  file.read_to_string(&mut input)?;
  Ok(input)
}

// shorter way

fn read_line_from_file() -> Result<String, io::Error> {
  let mut input = String::new();
  File::open("input.txt")?.read_to_string(&mut input)?;
  Ok(input)
}

에러의 종류가 여러가지로 예상된다면 반환되는 에러 타입을 Box<dyn error::Error>로 지정하면 된다.

'Archive > Rust' 카테고리의 다른 글

[Rustlings] 13. Option  (0) 2021.05.30
[Rustlings] 12. Generic  (0) 2021.05.29
[Rustlings] 10. String  (0) 2021.05.26
[Rustlings] 9. collection  (0) 2021.05.25
[Rustlings] 8. module  (0) 2021.05.22