728x90
반응형

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: PartialOrdT가 비교 가능한 타입임을 나타냅니다.

트레잇 (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는 asyncawait 키워드를 사용하여 비동기 프로그래밍을 지원합니다. 비동기 프로그래밍은 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;
      }
  • 고급 트레잇: 트레잇의 고급 기능 활용하기

    • 연관 타입: 트레잇에서 타입 플레이스홀더 정의
      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 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()
      }

참조: https://doc.rust-lang.org/book/ch19-00-advanced-features.html

728x90
반응형

'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

+ Recent posts