?
를 이용한 오류 전파
연산자 ?
는 호출자에게 오류를 반환할 때 사용합니다. 이를 이용하면 이런 코드를
match some_expression {
Ok(value) => value,
Err(err) => return Err(err),
}
이렇게 짧게 쓸 수 있습니다
some_expression?
이제 우리 예제에 적용해 보겠습니다:
use std::{fs, io}; use std::io::Read; fn read_username(path: &str) -> Result<String, io::Error> { let username_file_result = fs::File::open(path); let mut username_file = match username_file_result { Ok(file) => file, Err(err) => return Err(err), }; let mut username = String::new(); match username_file.read_to_string(&mut username) { Ok(_) => Ok(username), Err(err) => Err(err), } } fn main() { //fs::write("config.dat", "alice").unwrap(); let username = read_username("config.dat"); println!("username or error: {username:?}"); }
키 포인트:
username
변수는Ok(string)
이거나Err(error)
일 수 있습니다.fs::write
메서드를 사용하여 파일이 없거나, 비었거나, 중복되는 경우 등을 테스트해 봅니다.- 함수의 리턴 타입은 네스팅 되어 호출되는 함수의 리턴 타입과 호환되어야 합니다. 예를 들어
Result<T, Err>
를 리턴하는 함수는Result<AnyT, Err>
를 리턴하는 함수를 호출할 때에만?
를 사용할 수 있습니다.Option<AnyT>
나Result<T, OtherErr>
(OtherError
가From<Err>
를 구현하지 않는 다고 가정할 때)와 같은 타입을 리턴하는 함수를 호출할 때에는?
를 사용할 수 없습니다. 동일한 이유로,Option<T>
를 리턴하는 함수는Option<AnyT>
를 리턴하는 함수를 호출할 때에만?
를 사용할 수 있습니다.Option
과Result
간의 변환을 위해Option::ok_or
,Result::ok
,Result::err
와 같은 함수들을 사용할 수 있습니다.