Struct. In Rust we often want to group together some data and pass it to other functions for easier use. A struct can be used for this purpose.
With structs, we can have multiple fields. And we can add more fields (or remove them) without updating all references to the struct. This makes programs more maintainable.
Step 2 We initialize the struct using the "items" vector we just created (the compiler figures out that the "items" name fills the field).
Step 3 We pass the struct as an immutable reference to use_struct. This function cannot modify the struct, but can read its values.
struct Info {
items: Vec<String>,
id: usize,
}
fn use_struct(info: &Info) {
// Display some of the struct's fields.
println!("LEN = {} ID = {}", info.items.len(), info.id);
}
fn main() {
// Step 1: Create vector to place in new struct.
let mut items = vec![];
items.push(String::from("one"));
items.push(String::from("two"));
// Step 2: Create struct with items and id.
let info = Info { items, id: 0 };
// Step 3: Pass struct by reference to function.
use_struct(&info);
}LEN = 2 ID = 0
Mutable struct reference. What if we want to change a struct's fields in a function call? We can use a mutable reference to pass the struct to the function.
Here The update_house function can modify fields on the struct. It increases the "boards" field of the House.
struct House {
boards: usize,
}
fn update_house(house: &mut House) {
// Add boards to the house, which is behind a mutable reference.
house.boards += 2;
}
fn main() {
let mut house = House { boards: 0 };
// Pass a mutable reference to the struct to a function so it can be modified.
update_house(&mut house);
println!("BOARDS = {}", house.boards);
}BOARDS = 2
Nested struct. It is possible, and common, to nest structs in Rust. The structs are combined into one region of memory when the program runs, so there is no performance loss.
Here We place a Door struct inside the House struct. This could make code clearer that operates on a Door, but not a House.
struct House {
boards: usize,
door: Door,
}
struct Door {
color: String,
width: usize,
}
fn main() {
// Create a struct with a nested field struct (Door).
let mut house = House {
boards: 0,
door: Door {
color: String::from("red"),
width: 10,
},
};
println!("DOOR COLOR = {}", house.door.color)
}DOOR COLOR = red
Update syntax. It is possible create a struct without specifying all its fields. We can do this by specifying an existing struct to update the current struct with.
Part 1 We create Test struct by updating it with a const struct EMPTY. This provides default values for the fields.
Part 2 We can specify just one field, or multiple fields, along with the update syntax.
struct Test {
one: usize,
two: usize,
three: usize,
}
const EMPTY: Test = Test {
one: 1,
two: 2,
three: 3,
};
fn main() {
// Part 1: Use struct update syntax.
let t = Test { ..EMPTY };
println!("{} {} {}", t.one, t.two, t.three);
// Part 2: Update the empty struct with one new value.
let t = Test {
three: 900,
..EMPTY
};
println!("{} {} {}", t.one, t.two, t.three);
}1 2 3
1 2 900
Derive debug. When developing programs, we often want to know what a struct's contents are at a certain point. We can use println with a struct that has the Debug trait on it.
Packed struct. To reduce memory usage, we can place the packed attribute on a struct. This only works on structs that do not contain heap-allocated references.
Summary. Structs are a core part of almost all Rust programs. We can initialize them, use nested structs, and pass them as immutable or mutable references to functions.
Dot Net Perls is a collection of tested code examples. Pages are continually updated to stay current, with code correctness a top priority.
Sam Allen is passionate about computer languages. In the past, his work has been recommended by Apple and Microsoft and he has studied computers at a selective university in the United States.
This page was last updated on Nov 20, 2024 (edit link).