Understanding Structs in Rust Programming

Defining Structs in Rust

#[derive(Debug)]
struct UserProfile {
    username: String,
    dimensions: u32,
    length: u32,
}

Implementing Struct Methods

impl UserProfile {
    // Instance method
    fn calculate_area(&self) -> u32 {
        self.dimensions * self.length
    }
    
    // Method with multiple parameters
    fn is_larger_than(&self, other: &UserProfile) -> bool {
        self.dimensions > other.dimensions && self.length > other.length
    }
    
    // Associated function (static method)
    fn create_square(size: u32) -> UserProfile {
        UserProfile { 
            username: String::from(""), 
            dimensions: size, 
            length: size 
        }
    }
}

The impl keyword stands for implementation. The Self type is an alias for the type in the impl block. Methods must have a parameter named self of type Self. The &self syntax is shorthand for self: &Self, indicating the method borrows the instance.

To modify the instance in a method, use &mut self as the first parameter instead of &self. Methods with addditional parameters should place them after the self parameter.

Associated functions don't take self as a parameter, so they're not methods but rather associated with the struct type rather than an instance of it.

Using Structs

let user_profile = UserProfile { 
    username: String::from("rustacean"), 
    dimensions: 15, 
    length: 25 
};
println!("{:?}", user_profile);
println!("The area of profile {} is {}", user_profile.username, user_profile.calculate_area());

Field Initialization Shorthand

When function parameters have the same name as struct fields, you can use the shorthand syntax:

let profile1 = build_user_profile(String::from("developer"), 12, 18);
println!("{:?}", profile1);
println!("The area of profile {} is {}", profile1.username, profile1.calculate_area());

fn build_user_profile(username: String, width: u32, h: u32) -> UserProfile {
    UserProfile { username, width, length: h }
}

Struct Update Syntax

To create a new struct based on an existing one, use the .. syntax:

let profile2 = UserProfile {
    username: String::from("engineer"),
    ..profile1
};
println!("{:?}", profile2);
println!("The area of profile {} is {}", profile2.username, profile2.calculate_area());

The .. syntax indicates that the remaining fields should have the same values as the corresponding fields in the given instance.

Tuple Structs

Tuple structs have unnamed fields but are still distinct types:

struct RGB(u8, u8, u8);
let crimson = RGB(220, 20, 60);

Use tuple structs when you want a simple type with a few eelments but don't need to name each field. The struct name provides meaning to the tuple.

Unit-like Structs

Unit-like structs have no fields and are useful for traits when you don't need to store data:

struct Marker;
let identifier = Marker;

These structs take up no space since they don't have any fields.

Tags: rust Structs data-structures programming-patterns

Posted on Sat, 26 Sep 2026 16:42:36 +0000 by mattcooper