Structs: Defining Custom Data Types in Rust

A struct in Rust is a way to create a custom data type with named fields. Structs group related data together and give it structure. They are similar to JavaScript objects, but their fields and types must be explicitly declared.

Structs are essential when you want to represent real-world entities in your Rust programs. Instead of working with loose values or tuples, you define a clear, named structure for your data. In this post, I will explain how to define and use structs, including creating instances, accessing fields, and writing clean, reusable code.

What is a Struct?

A struct is a collection of named fields. Think of it like a JavaScript object, but with a fixed layout and declared types.

Example

struct User {
    name: String,
    age: u8,
    active: bool,
}

This defines a User type with three fields.

Creating an Instance

To create a struct, you use the struct name followed by key-value pairs:

let user1 = User {
    name: String::from("Alice"),
    age: 28,
    active: true,
};

You must match the field names and types exactly as defined.

Accessing Fields

You can read or update fields using dot syntax:

println!("Name: {}", user1.name);
println!("Age: {}", user1.age);

If the instance is mutable, you can change the values:

let mut user2 = User {
    name: String::from("Bob"),
    age: 30,
    active: false,
};

user2.active = true;

Field Init Shorthand

If your variable names match the field names, Rust lets you skip the key names:

fn build_user(name: String, age: u8) -> User {
    User {
        name, // same as name: name
        age,  // same as age: age
        active: true,
    }
}

This makes function-based struct creation cleaner.

Struct Update Syntax

You can create a new instance based on an existing one:

let user3 = User {
    name: String::from("Charlie"),
    ..user1
};

This copies all remaining fields from user1. The fields must implement the Clone or Copy traits if ownership is involved.

Tuple Structs

You can also define structs without field names:

struct Color(u8, u8, u8);

let red = Color(255, 0, 0);

Tuple structs work like tuples but with a distinct type name. These are useful when field names are not necessary but you still want type safety.

Unit-Like Structs

A struct with no fields is called a unit-like struct:

struct Marker;

let m = Marker;

These are often used for traits or markers in the type system.

Using Structs in Functions

You can pass structs as arguments and return them like any other value:

fn print_user(user: &User) {
    println!("{} is {} years old", user.name, user.age);
}

Use a reference to avoid moving or cloning the data.

Summary

Structs in Rust let you define your own types with named fields. They are powerful tools for organizing data and building real-world models in your code. Structs are the foundation for object-like design in Rust and work well with methods and traits.