Structs
/// We first define the struct's fields (which can be of any type). /// The `User` struct has four fields: `active`, `username`, `email`, and /// `sign_in_count`. #[derive(Debug)] struct User { active: bool, username: String, email: String, sign_in_count: u64, } // The `derive(Debug)` attribute is not required - it just enables `println!` // below. /// The `main` function creates an instance of the `User` struct. /// It then prints the struct to the console. fn main() { // Note that there is no `new` or similar. let user1 = User { active: true, username: String::from("someusername123"), email: String::from("someone@example.com"), sign_in_count: 1, }; println!("{:?}", user1); }
Struct fields follow the general rule of everything being private by default unless annotated with pub
⮳.
/// Represents a user with their active status, username, and email. #[derive(Debug)] struct User { active: bool, username: String, email: String, } // It is common to define a function (or an associated function, see below) that // initializes the struct: fn build_user(email: String, username: String) -> User { User { active: true, username, /* Field init shorthand, instead of writing `username: * username` */ email, // Same } } fn main() { // We create an instance of the struct: let user1: User = build_user("user@example.com".into(), "user".to_string()); // Then update the struct. // .. is used to fill in the rest let user2 = User { email: String::from("another@example.com"), ..user1 /* The remaining fields not explicitly set will have the * same value as the fields in the given instance. */ }; println!("{:?}", user2); }
/// A tuple struct. /// /// Note the ( ) and the lack of field names. #[derive(Debug)] struct Color(i32, i32, i32); /// A unit-like struct. /// /// Unit-like structs are useful when you need to implement a trait on /// something, but don't have any data that you want to store in the type /// itself. #[derive(Debug)] struct AlwaysEqual; // Note that there are no fields. fn main() { let black = Color(0, 0, 0); println!("{black:?}"); let s = AlwaysEqual; println!("{s:?}"); }
/// A struct representing a rectangle with a width and height. struct Rectangle { width: u32, height: u32, } /// Implementation block (multiple blocks are allowed for a given struct). impl Rectangle { /// Method: note the `self`: fn area(&self) -> u32 { // `&self` is short for `self: &Self`, an alias for the type that the // impl block is for. self.width * self.height } /// Associated Function. /// Note that there are NO `self`, `&self`, or `&mut self`. /// This is often used to define a "constructor": `SomeType::new(...)`. fn square(size: u32) -> Self { Self { width: size, height: size, } } } fn main() { // Call the associated function. // Note the syntax: `<Type>::<function>`. let sq: Rectangle = Rectangle::square(5); // Call the method. Note the dot. // This is equivalent to `Rectangle::area(sq)`. println!("Area: {}", sq.area()); }