Shiklo Tools
PDF40
Image20
Calculators & Converters25
Text & Writing13
Developer26
Video14
Audio14
Document14
Data & Spreadsheet12
Web & SEO9
OCR & Scanning5
Archive & File12
Security & Privacy23
Health & Medical29
QR & Barcode5

Rust Structs

Real things have several properties. A student has a name, a roll number and marks. A book has a title, an author and a number of pages. A struct (short for structure) lets you create your own type that groups these properties together under clear names. It is like designing a form with labelled boxes, and then filling in as many copies of the form as you need.

Defining and using a struct

struct Student {
    name: String,
    roll_number: u32,
    marks: f64,
}

fn main() {
    let asha = Student {
        name: String::from("Asha"),
        roll_number: 12,
        marks: 91.5,
    };
    println!("{} (roll {}) scored {}", asha.name, asha.roll_number, asha.marks);
}
Output
Asha (roll 12) scored 91.5

The definition, with struct, describes the shape: the names of the fields and their types. It is written outside main. Then Student { ... } creates an actual student, called an instance. You read a field with a dot: asha.name.

Struct names use CamelCase, with a capital letter for each word, like Student or BankAccount. That makes them easy to tell apart from variables.

Changing fields

To change a field, the whole instance must be mut. Rust does not let you mark only some fields as changeable:

struct Counter {
    label: String,
    value: u32,
}

fn main() {
    let mut visits = Counter { label: String::from("Visitors"), value: 0 };
    visits.value += 1;
    visits.value += 1;
    println!("{}: {}", visits.label, visits.value);
}
Output
Visitors: 2

A function that builds a struct

It is common to write a function that creates an instance. When a parameter has the same name as a field, you can write the name once; this is the field init shorthand:

struct Book {
    title: String,
    pages: u32,
}

fn new_book(title: &str, pages: u32) -> Book {
    Book { title: title.to_string(), pages }
}

fn main() {
    let books = vec![new_book("The Hobbit", 310), new_book("Matilda", 240)];
    for b in &books {
        println!("{} has {} pages", b.title, b.pages);
    }
}
Output
The Hobbit has 310 pages
Matilda has 240 pages

Printing a struct with Debug

println!("{}", asha) does not work for your own structs, because Rust cannot guess how you would like a student to look. But you can ask Rust to write a programmer's view for you with #[derive(Debug)] above the struct, and then print it with {:?}, or {:#?} for a tidier, multi-line view:

#[derive(Debug)]
struct Point {
    x: i32,
    y: i32,
}

fn main() {
    let p = Point { x: 3, y: 7 };
    println!("{:?}", p);
    println!("Distance from the corner: {}", p.x + p.y);
}
Output
Point { x: 3, y: 7 }
Distance from the corner: 10

derive asks the compiler to write some standard code for your type automatically. You will see it a lot, with other abilities such as Clone and PartialEq.

Practice exercises

  1. Make a Movie struct with a title, a year and a rating, create two movies and print them.
  2. Write fn older(a: &Person, b: &Person) -> &str that returns the name of the older person.
  3. Add #[derive(Debug)] to one of your structs and print it with {:#?}.