Error Handling In Rust

이정후·2023년 8월 15일
0

Rust

목록 보기
10/13
post-thumbnail

Rust에서는 에러를 처리하는데 몇 가지 기능이 있는데 그 중 panicResult에 대해 공부해봤다.

panic

작성한 프로그램에서 버그나 어떤 문제가 생기면 프로그램은 패닉에 빠진다. 몇 가지 예시로는

  • 배열의 범위 밖에 있는 인덱스에 접근할 때
  • 정수를 0으로 나눌 때
  • Option None 값에 unwrap할 때
  • Err 값인 Result에 expect를 사용할 때
    의 경우가 있다.
fn main() {
	panic!("The Panic..")
}

panic! 매크로 안의 메시지와 함께 패닉이 발생한 지점을 알려준다. main.rs파일의 두번째 줄에서 패닉이 발생했다.

또 한 backtrace를 사용할 수 있음을 알려준다.

backtrace

RUST_BACKTRACE 환경 변수를 설정하면 러스트가 해당 지점의 스택을 같이 전달해준다.

우선 Cargo.toml에 dependencies에 backtrace를 추가하고 프로젝트 터미널에
RUST_BACKTRACE=1 cargo run을 실행하면

$ RUST_BACKTRACE=1 cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.02s
     Running `target/debug/pr`
thread 'main' panicked at 'The Panic..', src/main.rs:2:5
stack backtrace:
   0: rust_begin_unwind
             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/panicking.rs:578:5
   1: core::panicking::panic_fmt
             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/panicking.rs:67:14
   2: pr::main
             at ./src/main.rs:2:5
   3: core::ops::function::FnOnce::call_once
             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/ops/function.rs:250:5

요렇게 나오게 된다.

Result

Result 타입은 실패 할 수도 있는 가능성에 대해 나타낸다. 예를 들어 어떤 파일을 여는데 해당 파일이 존재하지 않을 경우 패닉을 발생시켜 프로세스를 멈추는대신 파일을 새로 만드는것이 더욱 깔끔할지도 모른다.

Rust에서 Result는 열거형으로 OKErr라는 두 개의 variant를 가지고 있다.

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

Ok(T)는 성공했을때 나타내는 값을 반환하고, Err(E)는 에러를 나타내고 에러 값을 포함하는 값을 반환한다.

use std::fs::File;

fn main() {
	let my_file = File::open("hello.txt");
}

File::open은 아래와 같이 정의되어 있다.

pub fn open<P: AsRef<Path>>(&self, path: P) -> Result<File>

Result를 반환하는 것을 확인했으니, 이는 성공할 수도 실패할 수도 있다는 것을 알게되었다.

파일이 존재하지 않거나 파일에 접근할 권한이 없거나 등 다양한 상황에서, 위 함수를 통해 성공했는지 혹은 실패했는지 여부를 알려주면서 동시에 파일 핸들링이나 에러 핸들링을 할 수 있다.

만약 hello.txt 파일이 존재한다면 my_life 변수에는 Ok(T)의 인스턴스가 들어갈 것이고 실패할 경우는 Err(e)의 인스턴스가 될 것이다.

match

다시 처음으로 돌아와서, 파일이 없어서 실패한 것이라면 새로운 파일을 생성하고, 그것이 아니라면 패닉과 함께 에러 메시지를 리턴하고 싶다면,

use std::fs::File;
use std::io::ErrorKind;

fn main() {
    let my_file = File::open("hello.txt");

    let my_file = match my_file {
        Ok(file) => file,
        Err(ref error) if error.kind() == ErrorKind::NotFound => {
            match File::create("hello.txt") {
                Ok(fc) => fc,
                Err(e) => {
                    panic!(
                        "Tried to create file but there was a problem: {:?}",
                        e
                    )
                },
            }
        },
        Err(error) => {
            panic!(
                "There was a problem opening the file: {:?}",
                error
            )
        },
    };
}

실행전과 실행후의 차이, hello.txt 파일이 없으면 새로 생성하기까지 완료되었다.

profile
꾸준하게

0개의 댓글