강좌10-Struct 구조체
Struct에 대해 알아봅시다.
Struct는 변수의 모음이며, 마치 새로운 형을 선언하는 것처럼 변수의 형을 Struct로 선언할 수 있다는 특징이 있습니다.
1. 생성
c의 struct 또는 typescript의 interface와 같은 구조체를 만들 수 있습니다.
struct User {
name: String,
email: String,
age: u64,
active: bool,
}
2. 변수 선언
구조체 변수는 다음과 같이 선언합니다.
let user = User {
name: String::from("a"),
email: String::from("a@b.com"),
age: 10,
active: true
}
함수에서는 다음과 같이 사용합니다.
fn set_user(param: User) -> User {
User {
name: param.name,
email: param.email,
age: param.age
active: param.active
}
}
3. key 값의 생략
변수명과 key값이 동일한 경우 key를 생략할 수 있습니다.
또한, 생략과 생략하지 않는 경우를 함께 사용할 수도 있습니다.
fn main() {
let name = String::from("kim");
let email = String::from("kim@email.com");
let age = 10;
let user: User = User {
name,
email,
age,
active: true
};
}
그러나 이름이 다르면 에러를 발생하므로 유의 하여야 합니다.
fn main() {
let name1 = String::from("kim");
let email = String::from("kim@email.com");
let age = 10;
let active = true;
let user: User = User {
name1,
email,
age,
active
};
}
//결과
|
7 | name1,
| ^^^^^ help: a field with a similar name exists: `name`
4. 동일한 구조체의 다른 변수로부터 일부 값 가져오기
같은 구조체를 가진 다른 변수로 부터 전체 / 일부 값을 가져올 수 있습니다.
fn main() {
let user: User = User {
name: String::from("kim"),
email: String::from("kim@email.com"),
10,
true
};
let user2: User = User {
name: String::from("lee"),
email: String::from("lee@email.com"),
..user
};
let user3 = &user;
let rtn_usr = struct_fn(user);
}
user2는 일부, user3는 전체를 가져왔습니다.
user3에서 ..user로 전체 값을 가져오는 것은 가능할까요? 이 때, user는 어떻게 될까요?
fn main() {
let user: User = User {
name: String::from("kim"),
email: String::from("kim@email.com"),
10,
true
};
let user3 = ..user;
let rtn_usr = struct_fn(user);
}
//결과
|
2 | let user: User = User {
| ---- move occurs because `user` has type `User`, which does not implement the `Copy` trait
...
9 | let user3 = ..user;
| ---- value moved here
...
11 | let rtn_usr = struct_fn(user);
| ^^^^ value used here after move
user의 값은 user3로 move되었기 때문에 user의 ownership이 사라져 이후로 사용할 수 없으므로 에러가 발생합니다.
5. Tuple 형태로 구조체 만들기
구조체를 만들 때 Tuple을 활용하면 key없이 간단하게 구성할 수 있습니다.
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);
6. &str 형은 그대로 사용할 수 없다.
String형과는 달리 &str형은 구조체에서 그대로 사용할 수 없습니다.
이는 lifetime 때문인데 다른 챕터에서 더 자세히 알아보도록 하고,
여기에서는 &str은 구조체에 적합하지 않다. 라고만 이해하면 됩니다.
struct User {
name: &str,
email: String,
age: u64,
active: bool
}
fn main() {
let user: User = User {
key: "kim",
email: String::from("kim@email.com"),
age: 10,
active: true
};
}
// 에러 발생
|
2 | name: &str,
| ^ expected lifetime parameter
7. 함수에 구조체의 주소값만 넘기기
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
}
8. 구조체를 통째로 출력하기
구조체를 그대로 println의 인자로 넣으면 에러가 발생합니다
struct Rectangle {
width: u32,
height: u32,
}
fn main() {
let rect1 = Rectangle { width: 30, height: 50 };
println!("rect1 is {}", rect1);
}
// 결과
|
9 | println!("rect1 is {}", rect1);
| ^^^^^ `Rectangle` cannot be formatted with the default formatter
|
해결법은 간단한데 이전 챕터의 println 출력 옵션을 보면 {:?} 이 있습니다.
이를 활용하면 구조체를 그대로 출력할 수 있습니다.
struct Rectangle {
width: u32,
height: u32,
}
fn main() {
let rect1 = Rectangle { width: 30, height: 50 };
println!("rect1 is {:q}", rect1);
}
이번 강좌에서는 Struct의 기본 구조 및 편리한 사용 방법에 대해 알아보았습니다.
다음 강좌는 Struct의 확장에 대해 정리해보겠습니다.
댓글남기기