Lesson 10-Struct

3 분 소요

한국어(Korean) Page

Let’s delve into the concept of Structs in Rust.

A Struct is a collection of variables, characterized by the ability to declare a variable’s type as the Struct itself, effectively creating a new type.

1. Struct Definition

You can create structs resembling C’s structs or TypeScript’s interfaces.

struct User {
    name: String,
    email: String,
    age: u64,
    active: bool,
}

2. Struct Variable Declaration

Struct variables are declared as follows:

let user = User {
  name: String::from("a"),
  email: String::from("a@b.com"),
  age: 10,
  active: true
};

In function context:

fn set_user(param: User) -> User {
  User {
    name: param.name,
    email: param.email,
    age: param.age,
    active: param.active
  }
}

3. Key Omission

When the variable name and key are identical, the key can be omitted. You can also mix omitted and non-omitted keys.

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
    };
}

Be mindful that differing names will trigger an error.

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
    };
}

// Error:
//   |
// 7 |         name1,
//   |         ^^^^^ help: a field with a similar name exists: `name`

4. Acquiring Values from Other Struct Variables

You can acquire entire or partial values from other variables of the same struct type.

fn main() {
    let user: User = User {
        name: String::from("kim"),
        email: String::from("kim@email.com"),
        age: 10,
        active: 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 acquires some values, while user3 essentially gets a reference.

Is it possible to acquire all values using ..user in user3? And what happens to user?

fn main() {
    let user: User = User {
        name: String::from("kim"),
        email: String::from("kim@email.com"),
        age: 10,
        active: true
    };

    let user3 = ..user;
    
    let rtn_usr = struct_fn(user);
}

// Error:
//   |
// 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

Because the value of user is moved to user3, the ownership of user is lost, resulting in an error when user is used afterwards. This highlights the concept of ownership and move semantics in Rust.

5. Tuple Structs

Tuple structs allow a simpler struct definition without keys.

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

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

6. Immutability of &str in Structs

Unlike String, &str cannot be directly used in structs.

This is due to lifetimes, which will be covered in more detail in another chapter. For now, simply understand that &str is generally not suitable for structs without explicit lifetime management.

struct User {
    name: &str,
    email: String,
    age: u64,
    active: bool
}

fn main() {
    let user: User = User {
        name: "kim",
        email: String::from("kim@email.com"),
        age: 10,
        active: true
    };
}

// Error:
//   |
// 2 |     name: &str,
//   |           ^ expected lifetime parameter

7. Passing Structs by Reference

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. Printing Structs Directly

Attempting to directly pass a struct as an argument to println! results in an error.

struct Rectangle {
    width: u32,
    height: u32,
}

fn main() {
    let rect1 = Rectangle { width: 30, height: 50 };

    println!("rect1 is {}", rect1);
}

// Error:
//   |
// 9 |     println!("rect1 is {}", rect1);
//   |                             ^^^^^ `Rectangle` cannot be formatted with the default formatter
//   |

The solution is straightforward: use the {:?} debug formatting option within println!. This allows for direct struct output.

struct Rectangle {
    width: u32,
    height: u32,
}

fn main() {
    let rect1 = Rectangle { width: 30, height: 50 };

    println!("rect1 is {:?}", rect1);
}

This tutorial covered the basic structure and convenient usage of Structs in Rust.

The next tutorial will delve into Struct extensions and advanced features.

댓글남기기