Structs Basics
9 examples to get you started with structs - 6 basic and 3 intermediate.
Prerequisites
Basic Examples
1. Named Struct Definition
struct User {
id: u64,
active: bool,
}
fn main() {
let u = User { id: 1, active: true };
println!("{} {}", u.id, u.active);
}- Fields are named and typed
- Access with dot notation:
u.id - Order of fields in literal can differ from definition (since Rust 2021)
- Struct owns its fields unless they are references
Related: Methods & Associated Functions
2. Field Init Shorthand
struct Point { x: i32, y: i32 }
fn main() {
let x = 3;
let y = 4;
let p = Point { x, y };
println!("({}, {})", p.x, p.y);
}Point { x, y }expands toPoint { x: x, y: y }- Works when variable names match field names
- Reduces repetition in constructors
- Common in builder-style code
3. Tuple Struct
struct Meters(f64);
fn main() {
let d = Meters(10.0);
println!("{}", d.0);
}- Tuple structs give meaning to a single value (newtype pattern)
- Access tuple fields with
.0,.1, ... - Distinct from bare
f64despite same representation - Useful for units and IDs
4. Unit Struct
struct Marker;
fn main() {
let _m = Marker;
}- No fields - zero-sized type (ZST) often
- Used as markers in type state patterns
PhantomDataoften preferred for generic markers- Implements traits without carrying data
5. Update Syntax
struct Config { host: String, port: u16 }
fn main() {
let base = Config { host: "localhost".into(), port: 8080 };
let alt = Config { port: 3000, ..base };
println!("{}:{}", alt.host, alt.port);
}..basecopies remaining fields frombasebaseis moved field-by-field intoaltfor unspecified fields- After move of
host,base.hostis invalid - Pattern for variants on defaults
6. Mutable Struct Fields
struct Counter { value: u32 }
fn main() {
let mut c = Counter { value: 0 };
c.value += 1;
println!("{}", c.value);
}muton binding allows mutating fields- Individual fields cannot be
mutin struct def - Interior mutability uses
Cell/RefCellfor shared handles - Prefer methods encapsulating mutation
Intermediate Examples
7. Struct with References
struct Excerpt<'a> {
text: &'a str,
}
fn main() {
let article = String::from("Hello");
let e = Excerpt { text: &article };
println!("{}", e.text);
}- Lifetime parameter when storing borrows
Excerptcannot outlivearticle- Owned
Stringfield would not need'a - See Ownership section for lifetimes
8. #[derive(Debug)]
#[derive(Debug)]
struct Event { kind: u32, ts: u64 }
fn main() {
println!("{:?}", Event { kind: 1, ts: 99 });
}- Derive macros auto-implement common traits
Debugenables{:?}printing- Not all traits are derivable (
Displayneeds manual impl) - See Deriving Traits page
9. Destructuring Structs
struct Pair { a: i32, b: i32 }
fn sum(Pair { a, b }: Pair) -> i32 {
a + b
}
fn main() {
println!("{}", sum(Pair { a: 2, b: 3 }));
}- Pattern match extracts fields in
letandfnparams let Pair { a, .. } = pignores rest with..- Works in
matcharms - See Destructuring page
Related: Structs & Enums Best Practices
Stack versions: This page was written for Rust 1.97.0 (edition 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, and Polars 0.46+.