물음표 연산자 '?'
Coddy Rust 여정의 Logic & Flow 섹션에 포함된 레슨 — 66개 중 46번째.
Result를 반환하는 함수를 다룰 때, 에러를 로컬에서 처리하거나 호출한 함수로 전달하여 처리해야 하는 경우가 많습니다. 러스트(Rust)는 이러한 일반적인 패턴을 위해 우아한 연산자인 물음표 연산자 ?를 제공합니다.
? 연산자는 장황한 match 문을 작성하지 않고도 에러를 전파할 수 있는 깔끔한 방법을 제공합니다. Result 뒤에 ?를 붙이면, 자동으로 Ok 값을 언랩(unwrap)하거나 Err와 함께 현재 함수에서 즉시 반환됩니다:
fn parse_and_double(s: &str) -> Result<i32, std::num::ParseIntError> {
let number = s.parse::<i32>()?; // 파싱에 실패하면 에러를 반환합니다
Ok(number * 2) // 성공하면 숫자를 두 배로 만듭니다
}이것은 전체 match 문을 작성하는 것과 동일하지만, 훨씬 더 간결합니다. 만약 s.parse::<i32>()가 Ok를 반환하면, ?는 값을 추출하여 number에 할당합니다. 만약 Err를 반환하면, ?는 즉시 전체 함수에서 해당 에러를 반환합니다.
? 연산자는 에러를 반환할 수 있어야 하므로, Result(또는 Option)를 반환하는 함수에서만 사용할 수 있습니다.
챌린지
쉬움두 개의 입력을 받게 됩니다. 첫 번째 입력은 정수로 파싱되어야 하는 문자열이고, 두 번째 입력 또한 정수로 파싱되어야 하는 문자열입니다. 두 개의 문자열 슬라이스를 매개변수로 받고 Result<i32, std::num::ParseIntError>를 반환하는 add_numbers라는 함수를 만드세요. 함수 내부에서 ? 연산자를 사용하여 두 문자열을 모두 파싱하고, 그 합계를 Ok로 감싸서 반환하세요. 두 입력을 사용하여 함수를 호출하고 match를 사용하여 결과를 처리하세요.
요구 사항:
- 첫 번째 입력(문자열 형태의 첫 번째 숫자)을 읽고 공백을 제거합니다.
- 두 번째 입력(문자열 형태의 두 번째 숫자)을 읽고 공백을 제거합니다.
- 두 개의
&str매개변수를 받고Result<i32, std::num::ParseIntError>를 반환하는add_numbers함수를 만듭니다. - 함수 내부에서
?연산자를 사용하여 첫 번째 문자열을i32로 파싱합니다. ?연산자를 사용하여 두 번째 문자열을i32로 파싱합니다.- 두 파싱된 숫자의 합계인
Ok(sum)을 반환합니다. - 두 입력 문자열을 사용하여 함수를 호출합니다.
match표현식을 사용하여Result를 처리합니다.Ok(value)암(arm)에서는Sum: [value]를 출력합니다.Err(_)암(arm)에서는Parsing error를 출력합니다.
입력:
- 첫 번째 줄: 숫자를 나타내는 문자열 (예:
15) - 두 번째 줄: 또 다른 숫자를 나타내는 문자열 (예:
27)
출력:
- 두 문자열이 모두 유효한 숫자인 경우:
Sum: [result] - 어느 한 문자열이라도 파싱할 수 없는 경우:
Parsing error
치트 시트
물음표 연산자 ?는 Result를 반환하는 함수에서 에러를 전파하는 간결한 방법을 제공합니다.
Result 뒤에 위치할 때, ? 연산자는 다음과 같이 동작합니다:
Ok값을 언랩(unwrap)하고 실행을 계속합니다- 에러가 발생하면 현재 함수에서 즉시
Err를 반환합니다
fn parse_and_double(s: &str) -> Result<i32, std::num::ParseIntError> {
let number = s.parse::<i32>()?; // 파싱에 실패하면 에러를 반환합니다
Ok(number * 2) // 성공하면 숫자를 두 배로 만듭니다
}? 연산자는 Result 또는 Option 타입을 반환하는 함수에서만 사용할 수 있습니다.
직접 해보기
use std::io;
// TODO: 여기에 add_numbers 함수를 만드세요
// 이 함수는 두 개의 &str 매개변수를 받고 Result<i32, std::num::ParseIntError>를 반환해야 합니다
fn main() {
// 첫 번째 입력 읽기
let mut input1 = String::new();
io::stdin().read_line(&mut input1).expect("Failed to read line");
let input1 = input1.trim();
// 두 번째 입력 읽기
let mut input2 = String::new();
io::stdin().read_line(&mut input2).expect("Failed to read line");
let input2 = input2.trim();
// TODO: input1과 input2를 사용하여 add_numbers를 호출하세요
// TODO: match를 사용하여 Result를 처리하세요
// Ok(value)인 경우 "Sum: [value]"를 출력하세요
// Err(_)인 경우 "Parsing error"를 출력하세요
}이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
Logic & Flow의 모든 레슨
7'Result'를 이용한 에러 처리
'Result'란 무엇인가요?'Result'와 함께 'match' 사용하기is_ok()와 is_err()단축 방법: unwrap과 expect물음표 연산자 '?'문자열을 숫자로 파싱하기요약 - 안전한 나눗셈 함수