기본
Hello World
fn main() { println!("Hello, World!"); }
Cargo 명령어
cargo new my_project # create new project cargo build # compile (debug) cargo build --release # compile (optimized) cargo run # build and run cargo test # run tests
프로젝트 구조
Cargo.toml프로젝트 매니페스트 (의존성, 메타데이터)
src/main.rs바이너리 크레이트 진입점
src/lib.rs라이브러리 크레이트 루트
tests/통합 테스트 디렉터리
변수 및 가변성
바인딩 및 가변성
let x = 5; // immutable by default let mut y = 10; // mutable y += 1; const MAX: u32 = 100; // compile-time constant
섀도잉
let x = 5; let x = x + 1; // shadows previous x let x = "now a string"; // can change type
스칼라 타입
i8..i128, isize부호 있는 정수
u8..u128, usize부호 없는 정수
f32, f64부동소수점 (f64 기본값)
booltrue / false
char유니코드 스칼라 값 (4바이트)
복합 타입
let tup: (i32, f64, char) = (42, 6.4, 'z'); let (a, b, c) = tup; // destructure let arr: [i32; 3] = [1, 2, 3]; let first = arr[0];
함수
정의
fn add(a: i32, b: i32) -> i32 { a + b // no semicolon = return expression }
클로저
let double = |x: i32| x * 2; let sum: i32 = vec![1, 2, 3] .iter() .map(|x| x * 2) .sum();
함수 포인터 및 트레잇
fn(T) -> U함수 포인터 타입
Fn(T) -> U빌리는 클로저
FnMut(T) -> U가변 빌리는 클로저
FnOnce(T) -> U소유권을 가져가는 클로저
제어 흐름
If / Else
let status = if score >= 90 { "A" } else if score >= 80 { "B" } else { "C" }; // if is an expression
반복문
loop { break; } // infinite while condition { } // while for item in &vec { } // iterator for i in 0..10 { } // range for (i, v) in vec.iter().enumerate() { }
반복문 레이블
'outer: for i in 0..5 { for j in 0..5 { if i + j > 6 { break 'outer; } } }
소유권 및 빌림
소유권 규칙
1. 각 값에는 정확히 하나의 소유자가 있다. 2. 소유자가 범위를 벗어나면 값이 삭제된다. 3. 값은 이동하거나 복제할 수 있다.
이동 및 복제
let s1 = String::from("hello"); let s2 = s1; // s1 is moved, no longer valid let s3 = s2.clone(); // deep copy, both valid
빌림
fn len(s: &String) -> usize { s.len() } // shared ref fn push(s: &mut String) { s.push('!'); } // mutable ref // Rule: many &T OR one &mut T, never both
수명
fn longest<'a>(a: &'a str, b: &'a str) -> &'a str { if a.len() > b.len() { a } else { b } }
구조체 및 열거형
구조체
struct User { name: String, age: u32, active: bool, } let u = User { name: String::from("Alice"), age: 30, active: true };
Impl 블록
impl User { fn new(name: &str, age: u32) -> Self { Self { name: name.to_string(), age, active: true } } fn greeting(&self) -> String { format!("Hi, {}", self.name) } }
열거형
enum Shape { Circle(f64), Rect { w: f64, h: f64 }, Point, } let s = Shape::Circle(5.0);
패턴 매칭
Match 표현식
match shape { Shape::Circle(r) => std::f64::consts::PI * r * r, Shape::Rect { w, h } => w * h, Shape::Point => 0.0, }
If Let 및 While Let
if let Some(val) = optional { println!("{val}"); } while let Some(top) = stack.pop() { println!("{top}"); }
패턴 문법
_와일드카드, 모든 것 매칭
x @ 1..=5매칭된 범위를 x에 바인딩
(a, b, ..)튜플 구조 분해, 나머지 무시
Some(x) if x > 0매치 가드
Foo { x, .. }구조체, 다른 필드 무시
오류 처리
Result 및 Option
enum Result { Ok(T), Err(E) } enum Option { Some(T), None }
? 연산자
fn read_file(path: &str) -> Result { let mut s = String::new(); File::open(path)?.read_to_string(&mut s)?; Ok(s) }
오류 처리
match result { Ok(val) => println!("{val}"), Err(e) => eprintln!("Error: {e}"), } let val = result.unwrap_or(0); let val = result.unwrap_or_else(|_| default());
일반 메서드
.unwrap()값을 가져오거나 패닉
.expect(msg)값을 가져오거나 메시지와 함께 패닉
.unwrap_or(default)값을 가져오거나 기본값 사용
.map(f)Ok/Some 값 변환
.and_then(f)연산 체인 (flatmap)
.is_ok() / .is_some()불리언 확인
트레잇
정의 및 구현
trait Summary { fn summarize(&self) -> String; fn preview(&self) -> String { // default impl format!("{}...", &self.summarize()[..20]) } } impl Summary for User { fn summarize(&self) -> String { self.name.clone() } }
트레잇 바운드
fn notify(item: &impl Summary) { } fn notify(item: &T) { } fn notify(item: &(impl Summary + Display)) { }
일반 트레잇
Display사용자 대상 문자열 형식화
Debug디버그 형식화 ({:?})
Clone, Copy복제 (깊은 복사 / 비트 복사)
PartialEq, Eq동등 비교
PartialOrd, Ord순서 비교
Iterator반복을 위한 next()
From, Into타입 변환
Default기본값 생성자
컬렉션
Vec
let mut v: Vec = vec![1, 2, 3]; v.push(4); v.pop(); // returns Option let first = &v[0]; // panics if empty let first = v.get(0); // returns Option<&i32>
HashMap
use std::collections::HashMap; let mut m = HashMap::new(); m.insert("key", 42); m.entry("key").or_insert(0); if let Some(val) = m.get("key") { }
String
let s = String::from("hello"); let s = "hello".to_string(); let combined = format!("{} {}", s, "world"); for c in s.chars() { } // iterate characters
이터레이터
let sum: i32 = vec![1, 2, 3].iter().sum(); let doubled: Vec<_> = v.iter().map(|x| x * 2).collect(); let evens: Vec<_> = v.iter().filter(|x| *x % 2 == 0).collect();
동시성
스레드
use std::thread; let handle = thread::spawn(|| { println!("from spawned thread"); }); handle.join().unwrap();
채널
use std::sync::mpsc; let (tx, rx) = mpsc::channel(); tx.send(42).unwrap(); let val = rx.recv().unwrap();
공유 상태
Arc<T>원자적 참조 카운팅 (스레드 안전 Rc)
Mutex<T>상호 배제, 내부 값 접근을 위해 잠금
RwLock<T>여러 독자 또는 하나의 쓰기자
Send트레잇: 스레드 간 전송 안전
Sync트레잇: 스레드 간 참조 공유 안전
매크로 및 속성
일반 매크로
println!()개행 포함 출력
format!()형식화된 String 반환
vec![]리터럴로 Vec 생성
todo!()플레이스홀더, 런타임에 패닉
assert!(expr)expr이 false면 패닉
assert_eq!(a, b)a != b이면 패닉
파생 속성
#[derive(Debug, Clone, PartialEq)] struct Point { x: f64, y: f64 } // Auto-implements Debug, Clone, PartialEq
테스트 속성
#[cfg(test)] mod tests { use super::*; #[test] fn it_works() { assert_eq!(add(2, 2), 4); } #[test] #[should_panic] fn it_panics() { panic!("boom"); } }