Sling Academy
Home/Rust/Introduction to Rust Structs: A Foundational Overview

Introduction to Rust Structs: A Foundational Overview

Last updated: January 03, 2025

In the Rust programming language, structs are a fundamental tool that provide a simple way to create complex data types. Structs allow you to group related data and give them meaningful names, making your code more readable and maintainable. This foundational overview will help you understand how to define and use structs in Rust, along with examples to illustrate their power.

What are Structs?

In Rust, a struct, short for "structure," is a custom data type that lets you name and group together multiple related values of potentially different types. Structs are reminiscent of tuples, but unlike tuples, each piece of data, or field, is given a name. This naming can make understanding and maintaining the codebase easier as your program grows in size and complexity.

Defining Structs

To define a struct in Rust, you use the struct keyword followed by the struct name and the fields wrapped in curly braces. Here is a basic example:

struct Book {
    title: String,
    author: String,
    pages: u32,
    price: f32,
}

In this example, we define a Book struct with four fields: title, author, pages, and price. Each field has a name and associated type.

Instantiating Structs

After defining a struct, you can create instances of it. When instantiating a struct, you specify the field values in an order that matches their declaration:

let my_book = Book {
    title: String::from("The Rust Programming Language"),
    author: String::from("Steve Klabnik"),
    pages: 560,
    price: 40.0,
};

In this instance, my_book is a variable holding information about a book, using the types and identified fields declared earlier.

Accessing Fields

Once a struct is instantiated, you can access its fields using the dot notation. For example:

println!("Book Title: {}", my_book.title);
println!("Author: {}", my_book.author);

Here, we use dot notation to access and print the title and author fields of my_book.

Mutable Structs

Structs, like any variable in Rust, are immutable by default. However, you can make a struct mutable so that its fields can be changed after it’s created:

let mut my_book = Book {
    title: String::from("The Rust Programming Language"),
    author: String::from("Steve Klabnik"),
    pages: 560,
    price: 40.0,
};

my_book.price = 35.0;
println!("Discounted Price: {}", my_book.price);

Here, we change the price of my_book after it has been initialized, demonstrating the use of the mut keyword.

tuple Structs and unit-like Structs

Rust also provides tuple structs and unit-like structs. A tuple struct is a hybrid between a tuple and a traditional struct:

struct Color(i32, i32, i32);

You access the components of a tuple struct with the dot notation using indices:

let black = Color(0, 0, 0);
println!("Black: ({} {} {})", black.0, black.1, black.2);

A unit-like struct can be thought of as a struct without any fields:

struct AlwaysEqual;

These forms are less commonly used but can be helpful in advanced scenarios.

Benefits of Using Structs

Structs offer several benefits, including organization, reusability, and encapsulation of related properties in rust-based applications. They form the backbone for building more complex data structures as you develop in Rust.

Conclusion

Structs are a crucial building block in Rust programming that enable you to create organized and efficient data types tailor-made for your applications. They resemble but extend beyond traditional data storage mechanisms, offering semantic clarity that scales with complexity. By leveraging Rust's powerful support for structs, developers can write more robust, readable, and maintainable code.

Next Article: Defining Basic Structs in Rust and Their Named Fields

Series: Working with structs in Rust

Rust

You May Also Like

  • E0557 in Rust: Feature Has Been Removed or Is Unavailable in the Stable Channel
  • Network Protocol Handling Concurrency in Rust with async/await
  • Using the anyhow and thiserror Crates for Better Rust Error Tests
  • Rust - Investigating partial moves when pattern matching on vector or HashMap elements
  • Rust - Handling nested or hierarchical HashMaps for complex data relationships
  • Rust - Combining multiple HashMaps by merging keys and values
  • Composing Functionality in Rust Through Multiple Trait Bounds
  • E0437 in Rust: Unexpected `#` in macro invocation or attribute
  • Integrating I/O and Networking in Rust’s Async Concurrency
  • E0178 in Rust: Conflicting implementations of the same trait for a type
  • Utilizing a Reactor Pattern in Rust for Event-Driven Architectures
  • Parallelizing CPU-Intensive Work with Rust’s rayon Crate
  • Managing WebSocket Connections in Rust for Real-Time Apps
  • Downloading Files in Rust via HTTP for CLI Tools
  • Mocking Network Calls in Rust Tests with the surf or reqwest Crates
  • Rust - Designing advanced concurrency abstractions using generic channels or locks
  • Managing code expansion in debug builds with heavy usage of generics in Rust
  • Implementing parse-from-string logic for generic numeric types in Rust
  • Rust.- Refining trait bounds at implementation time for more specialized behavior