[Solana] Rust 기초

드림보이즈·2025년 4월 1일

2025 솔라나 해커톤

목록 보기
2/7

목표 : 솔라나 프로그래밍을 위한 언어인 Rust 기초 학습

주요 키워드 : Ownership, Lifetimes


나는 23년 말부터 두어달 Rust를 공부한 경험이 있다.
블록체인 클라이언트를 Rust로 개발하려고 했는데, 한달하고 포기했다.
생태계가 작아서 라이브러리가 적고, 오류 해결도 어렵다.
또 언어에 기능이 너무 많아서 일일히 기억하기 어렵다.
멀티 스레드 사용하고 싶은데 라이브러리는 비동기 싱글스레드면 못하고 복잡한게 한 둘이 아니었다.

영원히 볼 일 없을 줄 알았는데... 또 만났네?
아주 얕게, 기초만 훑어보고, 메인 학습은 솔라나 프로그래밍에서 하자.

1. Mutable, immutable

    // mutable, immutable
    let x = 5;
    let mut y = 10;
    y = 15;
    const MAX_POINTS: u32 = 100_000;

2. Data types

    // let vs const
    const HI : bool = true; // 타입 지정 필수, 전역 사용, 값 결정되어 있어야
    let z; // 타입 추론 가능, 전역 x, 런타임 할당 가능
    
    // data types
    let a : i32 = 42;
    let b : f64 = 3.14;
    let c : bool = true;
    let d : char = 'R';
    
    let tup :(i32,f64,u8) = (500,3.1,1);
    let arr : [i32;3] = [1,2,3];
    
    let mut s = String::from("hello");
    s.push_str(", world!");
    
    let slice : &str = &s[0..5]; // 슬라이스 : 기존 데이터 일부를 참조로 가져오기
    // 읽기는 가능하나 소유 안해서 복사 비용없이 사용 가능

3. control flow (if,for,while,match)

    // control flow
    let control_flow = 10;
    if control_flow > 5 {
        println!("i am bigger than 5");
    } else {
        println!("i am smaller than 5");
    }
    
    let control_flow_two = if control_flow > 5 {10} else {0};
    
    loop {
        println!("Infinite loop!")
        break;
    }
    
    let mut n = 3;
    while n > 0 {
        println!("{}", n);
        n -= 1;
    }
    
    for i in 1..4 {
        println!("{}", i);
    }
    
    let number = 3;
    match number {
        1 => println!("One");
        2 => println!("Two");
        _ => println!("Others");
    }
    

4. Functions

    // functions
    fn add(a:i32, b:i32) -> i32 {
        return a+b;
        
    }
    
    fn sqaure(x:i32) -> i32 {
        x * x // return, ; 빼고도 리턴 가능
    }
    
    let result1 = add(5,3);
    let result2 = sqaure(5);
    println!("Result : {}", result1);
    println!("Result : {}", result2);

5. Struct, Enums

    // Structure, enum
    struct User {
        username: String,
        email : String,
        active : bool,
    }
    
    let user1 = User {
        username : String::from("alice"),
        email : String::from("w.com");
        active : true,
    }
    
    enum IpAddr {
        V4(u8,u8,u8,u8),
        V6(String),
    }
    
    let home = IpAddr::V4(127,0,0,1);
    let loopback = IpAddr::V6(string::from("::1"));

6. Ownership & Move Sementics

value는 owner인 variable이 있다.
하나의 value는 하나의 owner만 가진다.
owner가 Out-of-scope시 value는 Drop된다.
뭔소린가 싶지? 코드를 보자.

    let s3 = String::from("block");
    {
        let s4 = s3; // s3 is moved into this block
        println!("Inside block : {}", s4);
    } // s4 is dropped
    // println!("{}", s3); // error : 

7. Reference & Borrowing

    // references & borring
    // &T : 읽기만 가능
    // &mut T : 데이터 변경 가능
    fn calculate_length(s : &string) -> usize {
        s.len()
    }
    let s1 = String::from("hello");
    let len = calculate_length(&s1);
    
    fn change(s: &mut String) {
        s.push_str(",world");
        
    }
    let mut s = String::from("hello");
    change(&mut s)
    

8. Traits

    // Traits (interface)
    
    trait Animal {
        fn eat(&self) -> String;
    }
    
    struct Human {
        name : String,
        age : i32,
    }
    
    impl Animal for Human {
        fn eat(&self) -> String {
            format!("{}...", &self.content[0..10])
        }
    }
    

9. Lifetimes

입력 중 짧은 라이프타임으로 통일시킨다.

    // Lifetimes
    // 두 입력 중 짧은 라이프타임으로 통일시킨다.
    fn longest<`a>(x : &`a str, y: &`a str) -> &`a str {
        if x.len() > y.len() {
            x
        } else {
            y
        }
    }
    
    let string1 = String::from("Long string is long");
    let result;
    {
        let string2 = String::from("short");
        result = longest(string1.as_str(), string2.as_str()) // result 수명 == string2
        // 
    }
    
    println!("{}", result) // error : string1은 ㅇㅋ, string2 못써서 result 못씀

Str vs String

fn main() {
    let s = "Hello, world!";  // &str 타입 (String literal)
    println!("{}", s);

    let string = String::from("Hello, Rust!");
    let slice = &string[0..5]; // &str 타입 (슬라이스)
    println!("{}", slice);     // 출력: Hello
}

10. Error Handling : Result, Option

    // Error handling
    fn divide(a: f64, b: f64) -> Result<f64, String> {
        if b == 0.0 { Err(String::from("Division by zero")) } else { Ok(a / b) }
    }

    fn find_char(s: &str, c: char) -> Option<usize> {
        for (i, ch) in s.chars().enumerate() {
            if ch == c {
                return Some(i);
            }
        }
    }
profile
시리즈 클릭하셔서 카테고리 별로 편하게 보세용

0개의 댓글