19장. 고급 기능
Rust는 안전성과 성능을 보장하면서도 다양한 고급 기능을 제공합니다.
Rust의 고급 기능 중 몇 가지를 설명합니다: 제네릭, 트레잇, 라이프타임, 매크로, 그리고 비동기 프로그래밍.
제네릭 (Generics)
제네릭은 함수, 구조체, 열거형 등을 정의할 때 구체적인 타입을 지정하지 않고, 다양한 타입을 처리할 수 있도록 합니다.
제네릭 함수 예제
fn largest<T: PartialOrd>(list: &[T]) -> &T {
let mut largest = &list[0];
for item in list {
if item > largest {
largest = item;
}
}
largest
}
fn main() {
let number_list = vec![34, 50, 25, 100, 65];
let result = largest(&number_list);
println!("The largest number is {}", result);
let char_list = vec!['y', 'm', 'a', 'q'];
let result = largest(&char_list);
println!("The largest char is {}", result);
}
위 예제에서 largest
함수는 제네릭 타입 T
를 사용하여 다양한 타입의 리스트에서 가장 큰 값을 찾습니다. T: PartialOrd
는 T
가 비교 가능한 타입임을 나타냅니다.
트레잇 (Traits)
트레잇은 객체의 동작을 정의하는 인터페이스입니다. 트레잇을 사용하여 구조체에 공통된 동작을 구현할 수 있습니다.
트레잇 예제
trait Summary {
fn summarize(&self) -> String;
}
struct Article {
headline: String,
content: String,
}
impl Summary for Article {
fn summarize(&self) -> String {
format!("{}: {}", self.headline, self.content)
}
}
fn main() {
let article = Article {
headline: String::from("Rust is great!"),
content: String::from("Rust is a systems programming language..."),
};
println!("New article available! {}", article.summarize());
}
위 예제에서 Summary
트레잇을 정의하고, Article
구조체에 대해 이를 구현했습니다. summarize
메서드는 Article
의 요약을 반환합니다.
라이프타임 (Lifetimes)
라이프타임은 참조자가 유효한 범위를 명시적으로 지정하여 메모리 안전성을 보장합니다.
라이프타임 예제
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
fn main() {
let string1 = String::from("long string is long");
let string2 = String::from("xyz");
let result = longest(&string1, &string2);
println!("The longest string is {}", result);
}
위 예제에서 longest
함수는 두 문자열 참조를 받아서 더 긴 문자열 참조를 반환합니다. 'a
라이프타임 매개변수는 반환되는 참조가 입력 참조들 중 하나와 동일한 라이프타임을 가짐을 보장합니다.
매크로 (Macros)
매크로는 코드 생성을 자동화하는 강력한 도구입니다. 매크로는 반복적인 코드 작성을 줄이고, 코드의 가독성과 유지보수성을 높입니다.
매크로 예제
macro_rules! say_hello {
() => {
println!("Hello!");
};
}
fn main() {
say_hello!();
}
위 예제에서 macro_rules!
를 사용하여 say_hello
매크로를 정의했습니다. say_hello!
매크로를 호출하면 "Hello!"를 출력합니다.
비동기 프로그래밍 (Asynchronous Programming)
Rust는 async
와 await
키워드를 사용하여 비동기 프로그래밍을 지원합니다. 비동기 프로그래밍은 I/O 작업과 같은 시간이 오래 걸리는 작업을 효율적으로 처리할 수 있게 합니다.
비동기 프로그래밍 예제
use tokio::time::{sleep, Duration};
async fn say_hello() {
sleep(Duration::from_secs(1)).await;
println!("Hello, world!");
}
#[tokio::main]
async fn main() {
say_hello().await;
}
위 예제에서 async fn
을 사용하여 비동기 함수를 정의하고, await
키워드를 사용하여 비동기 작업이 완료될 때까지 기다립니다. tokio
크레이트를 사용하여 비동기 런타임을 제공합니다.
Summary
Unsafe Rust: 안전하지 않은 Rust 코드 작성하기
- 원시 포인터: *const T와 *mut T를 사용한 직접적인 메모리 접근
let address = 0x012345usize; let r = address as *const i32;
- unsafe 함수 호출: unsafe fn 키워드로 선언된 위험한 함수 사용
unsafe fn dangerous() {} unsafe { dangerous(); }
- 전역 변수: static 키워드를 사용한 전역 상태 관리
static HELLO_WORLD: &str = "Hello, world!"; static mut COUNTER: u32 = 0;
- 외부 함수 인터페이스: C 코드와의 상호운용성
extern "C" { fn abs(input: i32) -> i32; }
- 원시 포인터: *const T와 *mut T를 사용한 직접적인 메모리 접근
고급 트레잇: 트레잇의 고급 기능 활용하기
- 연관 타입: 트레잇에서 타입 플레이스홀더 정의
pub trait Iterator { type Item; fn next(&mut self) -> Option<Self::Item>; }
- 기본 타입 매개변수: 제네릭 타입의 기본값 지정
trait Display<T = Self> { fn display(&self) -> String; }
- 완전 정규화 문법: 동일한 이름의 메서드 구분
trait Animal { fn baby_name() -> String; } <Dog as Animal>::baby_name()
- 연관 타입: 트레잇에서 타입 플레이스홀더 정의
고급 타입: 특수한 타입 시스템 기능
- 타입 별칭: type 키워드로 타입에 새로운 이름 부여
type Kilometers = i32; type Thunk = Box<dyn Fn() + Send + 'static>;
- Never 타입: 절대 반환되지 않는 함수의 반환 타입 !
fn bar() -> ! { panic!("이 함수는 절대 반환되지 않습니다"); }
- 동적 크기 타입: 컴파일 시점에 크기를 알 수 없는 타입
let s1: &str = "Hello there!"; let s2: Box<dyn Display> = Box::new(3);
- 타입 별칭: type 키워드로 타입에 새로운 이름 부여
고급 함수와 클로저: 함수형 프로그래밍 기능
- 함수 포인터와 스마트 포인터
type F = fn(i32) -> i32; let f: F = |x| x + 1;
- 클로저 반환하기
fn returns_closure() -> Box<dyn Fn(i32) -> i32> { Box::new(|x| x + 1) }
- 함수 포인터와 스마트 포인터
매크로: 메타프로그래밍 도구
- 선언적 매크로: macro_rules! 매크로
macro_rules! vec { ( $( $x:expr ),* ) => { { let mut temp_vec = Vec::new(); $( temp_vec.push($x); )* temp_vec } }; }
- 절차적 매크로: #[derive], 속성형, 함수형 매크로
#[proc_macro] pub fn make_answer(_item: TokenStream) -> TokenStream { "fn answer() -> u32 { 42 }".parse().unwrap() }
- 선언적 매크로: macro_rules! 매크로
참조: https://doc.rust-lang.org/book/ch19-00-advanced-features.html
'IT Best Practise > Rust' 카테고리의 다른 글
20. 웹서버 구현 (0) | 2024.11.07 |
---|---|
18. 패턴과 매칭 (0) | 2024.11.07 |
17. 객체지향 프로그래밍 (0) | 2024.11.07 |
16. 동시성 (0) | 2024.11.07 |
15. 스마트 포인터 (0) | 2024.11.07 |