Rust Structs
Define custom data structures in Rust using classic structs, tuple structs, unit structs, and implement methods with impl blocks.
Seventh post in the basic Rust series. Structs let you group related values into a single custom data type to model structured concepts in your programs.
Defining and instantiating structs#
A classic struct has named fields:
struct User {
active: bool,
username: String,
email: String,
sign_in_count: u64,
}
fn main() {
let user1 = User {
active: true,
username: String::from("alice"),
email: String::from("alice@example.com"),
sign_in_count: 1,
};
println!("User name: {}", user1.username);
}rustIf field names match variable names in scope, you can use field init shorthand:
fn build_user(email: String, username: String) -> User {
User {
active: true,
username,
email,
sign_in_count: 1,
}
}rustStruct update syntax#
Create a new instance using values from an existing instance with ..:
let user2 = User {
email: String::from("bob@example.com"),
..user1
};rustNote that field values with move semantics (like username in user1) will be moved into user2.
Tuple structs and unit-like structs#
Tuple structs have unnamed fields, identified by position:
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);rustUnit-like structs have no fields at all and are useful when implementing traits without holding state:
struct AlwaysEqual;
let subject = AlwaysEqual;rustMethods and impl blocks#
Define methods on a struct inside an impl block. The first parameter is usually &self (to borrow), &mut self (to mutate), or self (to take ownership):
struct Rectangle {
width: u32,
height: u32,
}
impl Rectangle {
fn area(&self) -> u32 {
self.width * self.height
}
fn can_hold(&self, other: &Rectangle) -> bool {
self.width > other.width && self.height > other.height
}
// Associated function (constructor)
fn square(size: u32) -> Self {
Self {
width: size,
height: size,
}
}
}
fn main() {
let rect1 = Rectangle { width: 30, height: 50 };
println!("Area: {}", rect1.area());
let sq = Rectangle::square(20);
println!("Can hold square? {}", rect1.can_hold(&sq));
}rustConclusion#
Structs allow you to create domain-specific types with named fields or tuple positions, and impl blocks organize behaviors alongside data. Next in this series: enums and pattern matching.