title: Structs

A struct groups related data together under a single name. Think of it like a record or object with named fields.

Defining and creating a struct

struct User {
    username: String,
    email: String,
    age: u32,
    active: bool,
}
 
let user = User {
    username: String::from("alice"),
    email: String::from("alice@example.com"),
    age: 30,
    active: true,
};

Accessing fields

println!("{}", user.username);  // "alice"

To mutate fields, the entire instance must be mut:

let mut user = User { ... };
user.age = 31;

Struct update syntax

Create a new instance based on an existing one, overriding only some fields:

let user2 = User {
    email: String::from("bob@example.com"),
    ..user  // copy remaining fields from user
};

Note: ..user moves any non-Copy fields, so user may be partially invalid after this.

Tuple structs

Structs without named fields — useful when the name alone gives enough context:

struct Point(f64, f64);
struct Color(u8, u8, u8);
 
let origin = Point(0.0, 0.0);
let red = Color(255, 0, 0);
 
println!("{}", origin.0);  // access by index

Methods

Methods are functions attached to a struct, defined inside an impl block. The first parameter is always self (the instance):

struct Rectangle {
    width: f64,
    height: f64,
}
 
impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
 
    fn scale(&mut self, factor: f64) {
        self.width *= factor;
        self.height *= factor;
    }
}
 
let mut rect = Rectangle { width: 10.0, height: 5.0 };
println!("{}", rect.area());  // 50.0
rect.scale(2.0);
println!("{}", rect.area());  // 200.0
  • &self — borrows the instance immutably (read only)
  • &mut self — borrows the instance mutably (can modify fields)
  • self — takes ownership (consumes the instance, rare)

Associated functions

Functions in impl that don’t take self are called associated functions. They’re often used as constructors:

impl Rectangle {
    fn square(size: f64) -> Self {
        Self { width: size, height: size }
    }
}
 
let sq = Rectangle::square(5.0);  // called with :: not .

Self is shorthand for the type being implemented (Rectangle here).