a struct is like an object’s data attributes.
inside curly brackets, we define the names and types of the pieces of data, which we call fields. For example,
struct User {
active: bool,
username: String,
email: String,
sign_in_count: u64,
}
**Listing 5-1: A User struct definition**
fn main() {
let user1 = User {
active: true,
username: String::from("someusername123"),
email: String::from("[email protected]"),
sign_in_count: 1,
};
}
user1.email = String::from("[email protected]");
**Listing 5-2: Creating an instance of the User struct, then modify the user1 email**
the entire instance must be mutable to mutate any field of the User instance
Using struct update syntax, we can achieve the same effect with less code, as shown in Listing 5-7. The syntax .. specifies that the remaining fields not explicitly set should have the same value as the fields in the given instance.
Filename: src/main.rs
fn main() {
// --snip--
let user2 = User {
email: String::from("[email protected]"),
..user1
};
}
**Listing 5-7: Using struct update syntax to set a new email value for a User instance but to use the rest of the values from user1**
we can no longer use user1 after creating user2 because the String in the username field of user1 was moved into user2.
To define a tuple struct, start with the struct keyword and the struct name followed by the types in the tuple. For example, here we define and use two tuple structs named Color and Point:
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
fn main() {
let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);
}
You can also define structs that don’t have any fields! These are called unit-like structs because they behave similarly to (),
fn main() {
let subject = AlwaysEqual;
}
Methods are similar to functions. but unlike functions, methods are defined within the context of a struct (or an enum or a trait object) and their first parameter is always self, which represents the instance of the struct the method is being called on.
Let’s change the area function that has a Rectangle instance as a parameter and instead make an area method defined on the Rectangle struct.
#[derive(Debug)]
struct Rectangle {
width: u32,
height: u32,
}
impl Rectangle {
fn area(&self) -> u32 {
self.width * self.height
}
}
fn main() {
let rect1 = Rectangle {
width: 30,
height: 50,
};
println!(
"The area of the rectangle is {} square pixels.",
rect1.area()
);
}