[Rust] Struct

silver·2023년 4월 28일
0

구조체를 정의하고 초기화하기

구조체는 튜플과 유사하게, 구성요소들이 각자 다른 타입을 지닐 수 있지만, 구성요소들을 각각 다르게 명명할 수 있어 값이 의미하는 바를 명확하게 할 수 있다. 구조체 내의 특정 요소 데이터 명세를 기술하거나, 접근할 때 순서에 의존할 필요가 없어 튜플보다 좀 더 유연하게 구성요소들을 다룰 수 있다.

구조체는 정의할 때는 struct 키워드를 먼저 입력하고 명명할 구조체 명을 입력하면 된다.

struct User {
	username: String,
    email: String,
    sign_in_count: u64,
    active: bool,
}

정의한 구조체는 아래와 같은 방식으로 사용할 수 있다.

let user = User {
	email: String::from("someone@example.com"),
    username: String::from("someusername123"),
    active: true,
    sign_in_count: 1,
}

변경이 가능한 구조체 인스턴스에 들어있는 값을 바꾸고자 할 때는, 점(.) 표기법을 사용하여 특정 필드에 새 값을 할당할 수 있다.

let mut user1 = User {
	email: String::from("someone@example.com"),
    username: String::from("someusername123"),
    active: true,
    sign_in_count: 1,
}

user1.email= String::from("anotheremail@example.com");

변수명이 필드명과 같을 때 간단하게 필드 초기화하기

변수명과 구조체의 필드명이 같다면, 필드 초기화 축약법(field init shorthand)을 이용할 수 있다. 이를 활용하면 구조체를 생성하는 함수를 더 간단히 작성할 수 있다.

fn build_user(email: String, username: String) -> User {
	User {
    	email,
        username,
        active: true,
        sign_in_count:1,
    }
}

구조체 갱신법을 이용하여 기존 구조체 인스턴스로 새 구조체 인스턴스 생성하기

존재하는 인스턴스에서 기존 값의 대부분은 사용하고, 몇몇 값만 바꿔 새로운 인스턴스를 정의하는 방법은 유용하다.

let user2 = User {
	email: String::from("another@example.com"),
    username: String::from("anotherusername567"),
    active: user1.active,
    sign_in_count: user1.sign_in_count,
}

구조체 갱신법(struct update syntax)은 입력으로 주어진 인스턴스와 변화하지 않는 필드들을 명시적으로 할당하지 않기 위해 .. 구문을 하용한다.

let user2 = User {
	email: String::from("another@example.com"),
    username: String::from("anotherusername567"),
    ..user1
}

이름이 없고 필드마다 타입은 다르게 정의 가능한 튜플 구조체

구조체명을 통해 의미를 부여할 수 있으나 필드의 타입만 정의할 수 있고 명명은 할 수 없는, 튜플 구조체(tuple structx)라 불리는 튜프로가 유사한 형태의 구조체도 정의할 수 있다.

struct Color(i32, i32, i32);
struct Point(i32, i32, i32);

let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);

blackorigin은 서로 다른 타입이란 것을 유념해야 한다. 구조체 내의 타입이 모두 동일하더라도 각각의 구조체는 고유의 타입이기 때문이다.

필드가 없는 유사 유닛 구조체

어떤 필드도 없는 구조체 역시 정의할 수 있다. 이는 유닛 탕비인 ()와 비슷하게 동작하고, 그때문에 유사 유닛 구조체(unit-like structs)라고 불린다. 유사 유닛 구조체는 특정한 타입의 트레잇(trait)을 구현해야하지만 타입 자체에 데이터를 저장하지 않는 경우 유용하다.

구조체 데이터의 소유권(Ownership)

위에서 User 구조체 정의에서는, &str 문자 슬라이스 타입 대신 String 타입을 사용했다. 이는 의도적인 선택으로, 구조체 전체가 유효한 동안 구조체가 그 데이터를 소유하게 하고자 함이다.

구조체가 소유권이 없는 데이터의 참조를 저장할 수는 있지만, 라이프타임(lifetimes)의 사용을 전제로 한다. 라이프타임은 구조체가 존재하는 동안 참조하는 데이터를 계속 존재할 수 있도록 한다. 라이프타임을 사용하지 않을 경우 아래와 같은 일이 발생한다.

struct User {
	username: &str,
    email: &str,
    sign_in_count: u64,
    active: bool,
}

fn main() {
	let user1 = User {
    	email: "someone@example.com",
        username: "someusername123",
        active: true,
        sign_in_count:1,
    };
}

다음과 같은 에러가 발생한다.

error[E0106]: missing lifetime specifier
 -->
  |
2 |     username: &str,
  |               ^ expected lifetime parameter

error[E0106]: missing lifetime specifier
 -->
  |
3 |     email: &str,
  |            ^ expected lifetime parameter

출처: https://rinthel.github.io/rust-lang-book-ko/ch05-01-defining-structs.html

0개의 댓글