Result 타입의 사용은 Rust에서 오류 처리를 위한 핵심 접근 방식 중 하나가 되었습니다. 역사적으로 많은 언어—예: C—에서 오류는 종종 특수 반환 값이나 전역 변수를 통해 신호가 주어졌으나, 이는 이러한 신호를 무시할 때 자주 발생하는 오류를 초래했습니다. Rust는 Result<T, E> 열거형을 사용하여 오류를 명시적으로 타입화하는 경로를 선택했으며, 이는 오류를 우연히 무시하는 것을 불가능하게 만들어 컴파일러가 성공과 실패의 두 가지 경로를 처리하도록 강제합니다.
문제: 오류 처리를 최대한 안전하고 읽기 쉽게 만들고 "숨겨진" 오류를 제거하며, 예외 없이 코드의 신뢰성을 높이는 것이 필요했습니다.
해결책: Result<T, E>는 두 가지 선택지를 가진 열거형입니다: 성공 시 Ok(T)와 오류 시 Err(E)입니다. 이는 오류를 명시적으로 처리하거나 unwrap를 통해 명시적으로 무시하거나 panics를 기다리도록 강요합니다. 또한, ? 연산자는 일반적인 오류 전파 패턴을 간결하게 만듭니다.
코드 예:
use std::fs::File; use std::io::{self, Read}; fn read_file(path: &str) -> Result<String, io::Error> { let mut file = File::open(path)?; let mut contents = String::new(); file.read_to_string(&mut contents)?; Ok(contents) }
주요 특징:
? 연산자를 통한 오류 전파 체인의 용이성.자동적으로 오류를 위로 전파하기 위해 항상 ? 연산자를 사용할 수 있습니까?
아니요, 함수의 오류 타입이 ? 오른쪽 표현식의 타입과 일치하는 경우에만 가능합니다. 타입이 호환되지 않으면 .map_err() 메서드 또는 사용자 정의 타입을 이용한 명시적 오류 변환이 필요합니다.
코드 예:
fn f() -> Result<(), String> { let _f = File::open("foo").map_err(|e| e.to_string())?; Ok(()) }
오류에 관심이 없으면 Result 결과를 사용하지 않을 수 있습니까?
아니요, Result 타입 결과가 처리되지 않으면 컴파일러가 경고 또는 오류를 표시합니다. .unwrap()을 호출하거나, .ok()/.err()/let _ = ...을 명시적으로 호출하거나, 오류를 올바르게 로깅해야 합니다.
오류가 있는 Result에서 .unwrap()을 호출하면 어떻게 됩니까?
panic!이 호출되고 프로그램의 실행이 중단됩니다. 일반적으로 이는 비정상 종료로 이어집니다. 따라서 unwrap()은 성공이 보장될 때만 허용됩니다.
let _ = ...;)? 사용 시 오류 타입 불일치로 인해 복잡한 컴파일 오류 발생개발자는 파일에서 구성 정보를 읽으려 하고 결과에 대한 unwrap()을 사용했습니다.
장점:
단점:
구성 정보를 읽는 오류는 로깅되고 Result + ? 연산자를 통해 호출 스택 위로 전파됩니다.
장점:
단점: