Expand description

A type that is composed of other types.

Structs in Rust come in three flavors: Structs with named fields, tuple structs, and unit structs.

struct Regular {
    field1: f32,
    field2: String,
    pub field3: bool
}

struct Tuple(u32, String);

struct Unit;
Run

Regular structs are the most commonly used. Each field defined within them has a name and a type, and once defined can be accessed using example_struct.field syntax. The fields of a struct share its mutability, so foo.bar = 2; would only be valid if foo was mutable. Adding pub to a field makes it visible to code in other modules, as well as allowing it to be directly accessed and modified.

Tuple structs are similar to regular structs, but its fields have no names. They are used like tuples, with deconstruction possible via let TupleStruct(x, y) = foo; syntax. For accessing individual variables, the same syntax is used as with regular tuples, namely foo.0, foo.1, etc, starting at zero.

Unit structs are most commonly used as marker. They have a size of zero bytes, but unlike empty enums they can be instantiated, making them isomorphic to the unit type (). Unit structs are useful when you need to implement a trait on something, but don’t need to store any data inside it.

Instantiation

Structs can be instantiated in different ways, all of which can be mixed and matched as needed. The most common way to make a new struct is via a constructor method such as new(), but when that isn’t available (or you’re writing the constructor itself), struct literal syntax is used:

let example = Foo {
    field1: 42.0,
    field2: "blah".to_string(),
    etc: true,
};
Run

It’s only possible to directly instantiate a struct using struct literal syntax when all of its fields are visible to you.

There are a handful of shortcuts provided to make writing constructors more convenient, most common of which is the Field Init shorthand. When there is a variable and a field of the same name, the assignment can be simplified from field: field into simply field. The following example of a hypothetical constructor demonstrates this:

struct User {
    name: String,
    admin: bool,
}

impl User {
    pub fn new(name: String) -> Self {
        Self {
            name,
            admin: false,
        }
    }
}
Run

Another shortcut for struct instantiation is available, used when you need to make a new struct that has the same values as most of a previous struct of the same type, called struct update syntax:

let updated_thing = Foo {
    field1: "a new value".to_string(),
    ..thing
};
Run

Tuple structs are instantiated in the same way as tuples themselves, except with the struct’s name as a prefix: Foo(123, false, 0.1).

Empty structs are instantiated with just their name, and don’t need anything else. let thing = EmptyStruct;

Style conventions

Structs are always written in CamelCase, with few exceptions. While the trailing comma on a struct’s list of fields can be omitted, it’s usually kept for convenience in adding and removing fields down the line.

For more information on structs, take a look at the Rust Book or the Reference.