Structure
structure유형은 여러 데이터를 저장 가능하고, 데이터마다 다른 타입 지정이 가능하다는 점에서 튜플유형과 유사하다. 튜플과의 차이점은 각 데이터의 명칭 부여 가능가 가능하기 때문에 데이터의 의미가 분명해지고, 튜플보다 유동적으로 데이터를 관리할 수 있다는 것이다.
1) 구조체 정의
struct User {
active: bool,
username: String,
email: String,
sign_in_count: u64,
}
2) 구조체 인스턴스 생성
모든 필드값을 채워주어야 한다.
let user1 = User {
email: String::from("it.progrowh@gmail.com"),
username: String::from("someuser"),
active: true,
sign_in_count: 1,
};
3) 구조체에서 특정 필드의 값 변경
let user1 = User {
email: String::from("it.progrowh@gmail.com"),
username: String::from("someuser"),
active: true,
sign_in_count: 1,
};
user1.email = String::from("rust@gmail.com");
4) 구조체를 생성하는 함수 만들기
email과 username을 받아서 User라는 structure을 만들 수 있다. 또한 email: email, 이라고 반복해서 쓰는 대신 email, username 식으로 축약해서 작성 가능하다.
fn build_user(email: String, username: String) -> User {
User {
email, // email: email 과 동일
username,
active: true,
sign_in_count: 1,
}
}
5) 업데이트1 : 다른 구조체의 값으로 새로운 structure 만들기
let user_update1 = User {
active: user1.active, // user1의 email 사용
username: user1.username, // user1의 username 사용
email: String::from("update@gmail.com"),
sign_in_count: user1.sign_in_count,
};
6) 업데이트2 : 축약버전 및 주의할 점
5)의 업데이트외에도 새로 정의하고 싶은 필드만 정의 한 뒤 아래와 같이 나머지 필드값을 불러와서 생성할 수 있다. 이때 가져온 user2는 이미 이곳에서 사용되었기 때문에 다시 이와 동일하게 사용될 수 없다. 주석의 내용은 5)에서 이미 user1이 사용되었기 때문에 이 곳에서 재사용될 수 없고 그렇기 때문에 user2가 사용된 것을 설명하였다.
let user_update2 = User {
email: String::from("update2@gmail.com"),
..user2 // user1에서 가져오려고 하면 이미 사용된 값이라 컴파일에러가 난다
};
7) Name 필드없이 튜플 Struct 사용
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
fn main(){
// 명명된 필드 없이 튜플 구조체를 사용하여 다른 유형 생성
let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);
}
8) 필드가 없는 단위 유사 구조체 : Unit-Like Structs without any fields
일반적으로 일부 유형에 특성을 구현해야 하지만, 유형 자체에 저장하려는 데이터가 없을때 유용하다. 항상 다른 모든 유형의 모든 인스턴스와 동일하도록하고 테스트 목적으로 사용한다. 사실 여기서는 어떻게 사용될지 정확하게 이해가 되지 않지만, 차차 알아가보도록 하자.
struct AlwaysEqual;
fn main(){
let subject = AlwaysEqual;
}
9) Struct 데이터의 소유권 : Ownership of struct data
앞에서 구조체를 사용할 때 문자열 슬라이스가 아닌 String 소유 유형을 사용했다. 이는 구조체의 각 인스턴스가 모든 데이터를 소유하고 전체 구조체가 유효한 동안 해당 데이터가 유효하도록 하기 위함이다. 구조체가 참조를 저장하는 것도 가능하지만, 이ㅏ는 10장의 lifetimes를 사용해야 한다. 따라서 아래와 같은 방법으로 참조를 저장하는 것은 에러가 난다.
struct UserOwnership {
active: bool,
username: &str, // ^ expected named lifetime parameter
email: &str, // ^ expected named lifetime parameter
sign_in_count: u64,
}
error[E0106]: missing lifetime specifier
이 후 Rust가이드 10장의 내용을 다룰 때 해당 에러를 어떻게 핸들링 할 지 알아보도록 하겠다.
Structs를 이용한 프로그램 예시
struct를 이용하기 전에 먼저, 간단하게 가로와 세로의 값으로 너비를 계산하는 함수를 만들어 보자. 간단한 내용이므로 변형되는 순서대로 코드만 살펴보고 넘어가도록 하겠다.
fn main() {
let width1 = 30;
let height1 = 50;
println!(
"The area of the rectangle is {} square pixels.",
area(width1, height1)
);
}
fn area(width: u32, height: u32) -> u32 {
width * height
}
The area of the rectangle is 1500 square pixels.
1) 튜플로 변형하기
fn main() {
let rect1 = (30, 50);
println!(
"The area of the rectangle is {} square pixels.",
area(rect1)
);
}
fn area(dimensions: (u32, u32)) -> u32 {
dimensions.0 * dimensions.1
}
2) Structs로 변경하기
우선 Rectangle이라는 구조체를 정의하고 rect1의 새로운 인스턴스를 선언한다. 다음으로 Rectangle을 받아 가로*세로를 계산해서 반환하는 함수로 고쳐준다.
struct Rectangle {
width: u32,
height: u32,
}
fn main() {
let rect1 = Rectangle {
width: 30,
height: 50,
};
println!(
"The area of the rectangle is {} square pixels.",
area(&rect1)
);
}
fn area(rectangle: &Rectangle) -> u32 {
rectangle.width * rectangle.height
}
3) Debug 사용
구조체를 프린트로 살펴보기 위해서는 아래와 같은 방법을 쓸 수 있다.
#[derive(Debug)]
struct Rectangle {
width: u32,
height: u32,
}
fn main() {
let rect1 = Rectangle {
width: 30,
height: 50,
};
println!("rect is {:#?}", rect);
println!("rect is {:?}", rect);
}
> rect is Rectangle {
> width: 30,
> height: 50,
> }
> rect is Rectangle { width: 30, height: 50 }
- 구조체 선언 윗 줄에 #[derive(Debug)]를 달아준다.
- :#? 은 보기 쉽게 줄바꿈을 하며 보여주고, :?를 한 줄로 보여준다.
4) dbg! 매크로(macro) 사용
#[derive(Debug)]
struct Rectangle {
width: u32,
height: u32,
}
fn main() {
let scale = 2;
let rect1 = Rectangle {
width: dbg!(30 * scale),
height: 50,
};
dbg!(&rect1);
}
&rect1 = Rectangle {
width: 60,
height: 50,
}
'Language > Rust' 카테고리의 다른 글
[Rust]Method syntax (0) | 2022.12.28 |
---|---|
[Rust]소유권 - string slice (0) | 2022.12.28 |
[Rust]소유권 - referrence, borrowing (0) | 2022.12.28 |
[Rust]Ownership 소유권 (0) | 2022.12.23 |
[Rust]Control Flow 제어문 (0) | 2022.12.22 |