많은 프로그래밍 언어는 null 값을 사용할 수 있게 허용하여, 실행 중에 null pointer dereference 오류를 초래합니다. 러스트에서는 옵셔널 값을 명시적으로 나타내기 위해 Option<T>라는 범용 타입을 도입하였으며, 이는 안전성을 보장하고, 중요하게도 값이 없는 경우를 고려하도록 강요합니다.
값이 없을 때(예: 검색 결과가 발견되지 않았을 때)는, 이를 타입에 반영하지 않으면 실행 중 오류가 발생하곤 합니다. 빈 값을 안전하고 명시적으로 관리하면, 버그의 양이 줄어듭니다.
Option<T> 타입은 두 가지 변형을 가진 enum으로 구현되어 있습니다: Some(T) (값이 존재함)과 None (값이 없음). 이는 컴파일러가 프로그래머에게 두 경우 모두를 고려하도록 강요할 수 있게 합니다. 옵셔널 값을 명시적 검사 없이 사용하는 것은 컴파일 오류로 이어집니다.
코드 예시:
fn divide(a: i32, b: i32) -> Option<i32> { if b == 0 { None } else { Some(a / b) } } let res = divide(6, 3); match res { Some(result) => println!("결과: {}", result), None => println!("제로 나누기 오류!"), }
주요 특징:
Option<T>는 zero-cost 추상화인가, 아니면 각 Option 변수가 더 많은 공간을 차지하는가?
대부분의 경우, Option<T>는 zero-cost입니다. 타입 T가 "null" 값을 가질 수 없을 때(예: 참조 타입이나 Box<T>)는 러스트가 "nullable pointer optimization"을 활용하여 추가적인 메모리가 필요하지 않습니다.
let value: Option<&u32> = None; // 일반적인 참조와 동일한 공간을 차지합니다.
unwrap를 사용해도 괜찮은가?
아니요, unwrap()은 값이 None일 때 패닉을 발생시킵니다. 값이 존재한다고 확실히 보장되는 경우에만 사용해야 하며, unwrap_or, unwrap_or_else 또는 패턴 매칭을 사용하는 것이 좋습니다.
Option과 참조 (&T, Option<&T>)의 차이점은 무엇인가?
참조는 항상 존재하는 값을 가리킵니다. 값이 없으면, "아무것도 있을 수 있음"을 명시적으로 표현하기 위해 Option<&T>를 사용해야 합니다. 직접 참조 대신 Option을 사용하면 null 포인터 경쟁을 방지합니다.
함수가 Option을 통해 검색 결과를 반환하지만, 호출하는 코드가 항상 결과가 있다고 믿고 unwrap를 사용합니다. 실제로 값이 없으면 프로그램이 production에서 중단됩니다.
장점:
단점:
코드가 옵션 처리에 대해 match를 사용하여, 모든 경우가 명시적으로 문서화되고 테스트로 커버됩니다.
장점:
단점: