(Rust) 에러 전파 연산자 정리
Rust의 ?는 성공 값은 꺼내고 실패 값은 현재 함수의 반환값으로 바꾸어 호출자에게 전달하는 연산자.
write!와 ?의 흐름 차이
write!(formatter, ", ")?;
write!의 반환 타입은 출력 대상의 write_fmt가 정함. 위 코드처럼 fmt::Formatter에 쓰면 fmt::Result, std::io::Write 구현에 쓰면 보통 io::Result를 반환함.
- Ok(())이면 다음 코드로 진행함
- Err(error)이면 현재 함수를 끝내고 에러를 호출자에게 반환함
match로 작성해보기
Result에 사용한 ?는 단순화하면 아래 흐름으로 볼 수 있음.
match write!(formatter, ", ") {
Ok(()) => {}
Err(error) => return Err(From::from(error)),
}
From::from이 보이는 이유는 원래 에러와 함수가 반환하는 에러의 타입이 다를 수 있기 때문.
실제 언어 정의는 Try와 FromResidual을 사용하지만, Result의 일반적인 동작은 이 형태로 이해할 수 있음.
Display 구현
Display::fmt는 fmt::Result를 반환하므로 같은 타입을 반환하는 write! 뒤에 ?를 붙일 수 있음.
use std::fmt;
struct Point {
x: i32,
y: i32,
}
impl fmt::Display for Point {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "({}, ", self.x)?;
write!(formatter, "{})", self.y)
}
}
첫 번째 write!가 실패하면 두 번째 호출은 실행되지 않음.
성공하면 다음 줄로 넘어가고, 마지막 write!의 결과를 그대로 반환함.
?를 쓰는 함수의 반환 타입은 전달할 실패 값을 받을 수 있어야 함.
Result 안에서는 Result, Option 안에서는 Option을 전파하며 서로 임의로 섞이지 않음.
use std::num::ParseIntError;
fn parse_number(text: &str) -> Result<i32, ParseIntError> {
let value = text.parse::<i32>()?;
Ok(value)
}
text.parse()가 Err를 반환하면 parse_number도 그 지점에서 끝남.
Ok라면 내부의 i32를 value에 넣고 다음 줄을 실행.
(참고)
'Rust' 카테고리의 다른 글
| (Rust) 참조와 역참조 정리 (*, &) (0) | 2026.09.09 |
|---|---|
| (Rust) use와 match 정리 (0) | 2026.09.09 |
| (Rust) Display와 Debug 출력 형식 비교 (0) | 2026.09.08 |
| (Rust) Copy와 Clone 차이점 정리 (0) | 2026.07.04 |
| (Rust) 소유권 (Ownership) 이해하기 (0) | 2026.07.04 |