- 변수를 정의할 때는 let 키워드를 사용한다.
- 타입 추론을 지원하기에 타입 정의 부분을 생략해도 된다.
let thing1: i32 = 100;
let thing2 = 200 + thing1;
// mut은 mutable을 의미하는 것으로, 수정 가능한 변수인지를 표현한다.
let mut changing_thing = true;
changing_thing = false;
let (part1, part2) = ("first", "second");
struct Example {
a: bool,
b: u64,
}
let Example { a, b: _ } = Example {
a: true,
b: 10004,
};
assert!(a);
// 변수 이름을 shadowing 해서 정의할 수도 있다.
// shadowing을 하면 새로운 변수가 생기며, 이전 변수와 새 변수는 메모리의 서로 다른 위치에 존재한다.
let shadowing_example = true;
let shadowing_example = 123.4;
let shadowing_example = shadowing_example as u32;
let mut shadowing_example = format!("cool! {shadowing_example}");
shadowing_example += " something else!"; // not shadowing
println!("{shadowing_example}")
const
로 선언하면 컴파일 할 때 그 값이 정해지며, 상수가 사용되는 모든 부분에서 인라인된다.static
변수는 프로그램이 수행되는 동안 유지되며, 다른 변수로 이동(move)되지 않는다.
이름 | 타입 | 비트 | 리터럴 값 |
---|---|---|---|
부호있는 정수 | i8 , i16 , i32 , i64 , i128 (isize 는 포인터 크기) |
N 비트 (알파벳 뒤의 숫자와 동일) | -10 , 0 , 1_000 , 123_i64 |
부호없는 정수 | u8 , u16 , u32 , u64 , u128 (isize 는 포인터 크기) |
N 비트 | 0 , 123 , 10_u16 |
부동소수 | f32 , f64 |
N 비트 | 3.14 , -10.0e20 , 2_f32 |
문자열 | &str |
포인터 크기 | "foo" , "two\nlines" |
유니코드 문자 | char |
32 비트 | 'a' , 'α' , '∞' |
불린 | bool |
8 비트 | true , false |
이름 | 타입 | 리터럴 값 |
---|---|---|
배열 | [T; N] |
[20, 30, 40], [0; 3] |
튜플 | (), (T,), (T1, T2), … |
(), ('x',), ('x', 1.2), … |
-
배열
-
배열은 같은 타입 T의 값이 N개 있는 것이고 N은 컴파일 타임에 결정된 값이어야 한다.
-
길이도 배열 타입의 일부이기에,
[u8; 3]
와[u8; 4]
은 서로 다른 타입이다.```rust fn main() { let mut a: [i8; 10] = [42; 10]; a[5] = 0; println!("a: {:?}", a); } ```
-
배열의 일부를 슬라이스 해서 가져올 수 있다.
-
슬라이스는 큰 컬랙션의 일부(혹은 전체)를 보여주는 뷰(view)이며, 다른(슬라이스 된) 타입으로부터 데이터를 빌려온다. 다시말해 소유권을 갖지 않는다.
-
메모리 안전을 위해 슬라이스가 선언, 사용될 때는 원본 배열과 슬라이스 배열을 수정할 수 없다. 슬라이스가 사용되지 않을 때, 즉 슬라이스를 만들기 전이나, 혹은 println이후에는
a[3]
을 바꿀 수 있다.fn main() { let mut a: [i32; 6] = [10, 20, 30, 40, 50, 60]; println!("a: {a:?}"); // 인덱스 0부터 시작한다면 시작 인덱스는 생략 가능하다. let a1: &[i32] = &a[..a.len()] // = &a[0..a.len()] // 마지막 인덱스도 생략 가능하다. let a1: &[i32] = &a[2..] // = &a[2..a.len()] // 전체 배열에 대한 슬라이스는 &a[..] let s: &[i32] = &a[2..4]; println!("s: {s:?}"); }
-
-
튜플
-
튜플은 서로 다른 타입의 값들을 하나의 복합 타입으로 묶는다.
-
튜플에 속한 값은
t.0
,t.1
과 같이 인덱스로 접근할 수 있다. -
비어있는 튜플
()
은 단위 타입(unit type)이라고 하고, 함수나 식에서 반환 값이 없음을 나타낼 때 사용한다. (다른 언어의void
개념과 비슷하다.)```rust fn main() { let t: (i8, bool) = (7, true); println!("1st index: {}", t.0); println!("2nd index: {}", t.1); } ```
-
&
를 통해서 포인터를 선언하고, *
를 통해 역참조할 수 있다.
let mut ref_x: &i32
와let ref_x: &mut i32
는 다른 의미이다. 첫번째 값은 다른 값에 바인딩 될 수 있는 가변 참조이고, 두번째 값은 가변 값에 대한 참조이다.
fn main() {
let mut x: i32 = 10;
let ref_x: &mut i32 = &mut x;
*ref_x = 20;
println!("x: {x}");
}
- 러스트는 열거형 variant를 구분하기 위해 내부적으로 식별자(discriminant) 필드를 사용한다.
// 일반 enum
enum CoinFlip {
Heads,
Tails,
}
// 데이터를 포함하는 enum (Variant Payloads)
enum WebEvent {
PageLoad, // Variant without payload
KeyPress(char), // Tuple struct variant
Click { x: i64, y: i64 }, // Full struct variant
}
#[rustfmt::skip]
fn inspect(event: WebEvent) {
match event {
WebEvent::PageLoad => println!("page loaded"),
WebEvent::KeyPress(c) => println!("pressed '{c}'"),
WebEvent::Click { x, y } => println!("clicked at x={x}, y={y}"),
}
}
fn main() {
let load = WebEvent::PageLoad;
let press = WebEvent::KeyPress('x');
let click = WebEvent::Click { x: 20, y: 80 };
inspect(load);
inspect(press);
inspect(click);
}
참고