Struct types

Structs in Rust have a few different ways to be defined, each having their own use cases.

Learn Rust by Practice

Master Rust through hands-on coding exercises and real-world examples.

Structs with named fields

The most common one is structs with named fields, here's an example of a struct with named fields:

struct Point {
    name: String,
    x: i32,
    y: i32,
}

Each field in the struct can have a different type. The fields can be accessed using the dot notation:

let p = Point { name: String::from("origin"), x: 0, y: 0 };
println!("The point is at ({}, {})", p.x, p.y);

Tuple structs

Tuple structs do not have named fields, but rather just the types of the fields. They are especially useful when you know the struct type doesn't need too many fields, so there's no need to name them.

Here's an example of a tuple struct:

struct Color(i32, i32, i32);

In the example above of a Color struct, we don't need to name the fields, as it's clear that the three integers represent the red, green, and blue values of the color.

Tuple structs are accessed using the dot notation and the index of the field, the first field has index 0, the second has index 1, and so on:

let c = Color(255, 0, 0);
println!("The color is RGB ({}, {}, {})", c.0, c.1, c.2);

Unit structs

Unit structs are structs that don't have any fields. They are useful when you need to implement a trait on a type (more on traits and implementations later), but don't need to store any data. They are called unit structs because they have the type of () (unit type), as discussed earlier in the data types lesson.

If you only need to implement a trait on a type, you can use a unit struct:

struct Empty;

Here's an example of a unit struct. Let's say we have a trait Describable that defines a method describe. Here's how you can define and implement this:

// Define a unit struct
struct UnitStruct;
 
// Define a trait with a method `describe`
trait Describable {
    fn describe(&self) -> String;
}
 
// Implement the Describable trait for UnitStruct
impl Describable for UnitStruct {
    fn describe(&self) -> String {
        "This is a unit struct implementing the Describable trait.".to_string()
    }
}
 
fn main() {
    let another_unit = UnitStruct;
    println!("{}", another_unit.describe()); // Call the describe method and print the result
}

Don't worry if you don't quite understand traits and implementations yet, we'll cover them in detail in a later lesson.

Conclusion

There are three ways to define structs in Rust: structs with named fields, tuple structs, and unit structs.

Each has its own use cases, and you should choose the one that best fits your needs. Structs with named fields are the most common and are used when you need to name each field. Tuple structs are used when you don't need to name the fields, and unit structs are used when you don't need to store any data.

// Struct with named fields
struct Point {
    name: String,
    x: i32,
    y: i32,
}
 
// Tuple struct
struct Color(i32, i32, i32);
 
// Unit struct
struct Empty;

In the next lesson, we're going to explore implementations, what they are, how they work, and how to use them with structs.