Option과 unwrap
지난 예제에서, 우리는 프로그램을 의도적으로 실패하게 만들 수 있음을 보여주었습니다. 설탕이 든 레모네이드를 마시면 panic하도록 프로그램에 지시했습니다. 하지만 음료가 있을 것으로 예상했는데 아무것도 받지 못하면 어떨까요? 그 경우도 마찬가지로 나쁠 것이므로, 처리가 필요합니다!
레모네이드의 경우처럼 빈 문자열("")인지 테스트할 수도 있습니다. 하지만 우리는 Rust를 사용하고 있으니, 대신 컴파일러가 음료가 없는 경우를 지적하도록 해봅시다.
표준 라이브러리의 Option<T>라는 열거형은 부재의 가능성이 있을 때 사용됩니다. 이는 두 가지 “옵션” 중 하나로 나타납니다:
Some(T):T타입의 요소가 발견됨None: 요소가 발견되지 않음
이러한 경우들은 match를 통해 명시적으로 처리하거나 unwrap을 통해 암시적으로 처리할 수 있습니다. 암시적 처리는 내부 요소를 반환하거나 panic을 일으킵니다.
expect를 사용하여 panic을 수동으로 커스터마이징할 수 있지만, 그렇지 않으면 unwrap은 명시적 처리보다 덜 의미 있는 출력을 남깁니다. 다음 예제에서, 명시적 처리는 원하는 경우 panic할 수 있는 옵션을 유지하면서도 더 제어된 결과를 제공합니다.
// 어른은 모든 것을 보았고, 어떤 음료든 잘 다룰 수 있습니다.
// 모든 음료는 `match`를 사용하여 명시적으로 처리됩니다.
fn give_adult(drink: Option<&str>) {
// 각 경우에 대한 행동 지침을 지정합니다.
match drink {
Some("레모네이드") => println!("윽! 너무 달아요."),
Some(inner) => println!("{}요? 좋네요.", inner),
None => println!("음료가 없나요? 뭐, 어쩔 수 없죠."),
}
}
// 다른 사람들은 단 음료를 마시기 전에 `panic`할 것입니다.
// 모든 음료는 `unwrap`을 사용하여 암시적으로 처리됩니다.
fn drink(drink: Option<&str>) {
// `unwrap`은 `None`을 받으면 `panic`을 반환합니다.
let inside = drink.unwrap();
if inside == "레모네이드" { panic!("으아아아아!!!!"); }
println!("난 {}가 너무 좋아요!!!!!", inside);
}
fn main() {
let water = Some("물");
let lemonade = Some("레모네이드");
let void = None;
give_adult(water);
give_adult(lemonade);
give_adult(void);
let coffee = Some("커피");
let nothing = None;
drink(coffee);
drink(nothing);
}