Перейти к основному содержимому
  1. Rust/

Создание и использование структур в Rust: Практическое руководство

770 слов·4 минут· loading · loading · ·
Rust Dev
about-rust - Эта статья часть цикла.
Часть 4: Эта статья

Введение. Что такое структура
#

Структура (или struct) в Rust — это пользовательский тип данных, который позволяет группировать связанные данные вместе. Структуры похожи на классы в других языках программирования, но в Rust (как говорит документация) они более гибкие и мощные, так как язык предоставляет различные возможности для работы с ними. Кто бы сомневался 😁 При этом видов структур существует несколько.

В этой главе остановлюсь на простой классической C структуре.

Первый шаг. Проектирование структуры
#

Прежде чем писать код, важно спроектировать и описать, что мы хотим получить. Давайте возьмем нашу любимую тему по системам для управления умным домом. В нашей системе есть хаб (центральное устройство) и несколько сенсоров, которые подключены к этому хабу.

Диаграмма классов
#

classDiagram class HUB { +String name +String id +String location +Vec~Sensor~ sensors } class Sensor { +String name +String id +String type +f32 value +String unit +bool isActive } HUB "1" --> "n" Sensor : хаб хранит сенсоры

Описание структур и полей:
#

  • HUB:

    • name: String — имя хаба.
    • id: String — уникальный идентификатор хаба.
    • location: String — местоположение хаба.
    • sensors: Vec[Sensor] — список сенсоров, подключенных к хабу.
  • Sensor:

    • name: String — имя сенсора.
    • id: String — уникальный идентификатор сенсора.
    • type: String — тип сенсора (например, “температура”, “влажность” и т.д.).
    • value: f32 — текущее значение, измеренное сенсором.
    • unit: String — единица измерения (например, “°C”, “%” и т.д.).
    • isActive: bool — статус сенсора (активен/неактивен).

Шаг 2. Создание структур в Rust
#

Теперь, когда мы спроектировали наши структуры, давайте перейдем к их реализации в Rust.

Определение структур
#

// // Игнорируем предупреждения о неиспользуемом коде
#![allow(dead_code)]

#[derive(Debug)]
struct Hub {
    name: String,
    id: String,
    location: String,
    sensors: Vec<Sensor>,
}

#[derive(Debug)]
struct Sensor {
    name: String,
    id: String,
    sensor_type: String,
    value: f32,
    unit: String,
    is_active: bool,
}

Здесь мы определили две структуры: Hub и Sensor.

Обратите внимание на использование атрибута #[derive(Debug)], который позволяет нам выводить содержимое структур с помощью макроса println!.

Синтаксис довольно простой: struct Имя_структуры далее в фигурных скобках через запятую указываются поля.

С типом String должны быть многие знакомы, это просто UTF-8 строка. Но rust был бы не растом если бы было так просто, но об этом в другой раз. Кому интересно можно прочитать про тип str - https://doc.rust-lang.org/std/primitive.str.html

Vec - это массив который хранит сенсоры (тип объекта который он хранит указывается в угловых скобках). Мощный тип Vec с множеством методов, дартовская библиотека collection позавидует.

f32 - это обычный float. Подробнее в доке - https://doc.rust-lang.org/std/primitive.f32.html

bool - это логический тип boolean (true/false) - https://doc.rust-lang.org/std/primitive.bool.html

C описанием полей закончили. Переходим к тому как с этим всем работать.

Создание экземпляров структур
#

Теперь создадим экземпляр структуры Hub


// код выше остается таким же
...
fn main() {
    let  hub = Hub {
    name: "Main Hub".to_string(),
    id: String::from("HUB001"),
    location: "Room 101".to_string(),
    sensors: Vec::new(), // Инициализация пустого списка сенсоров
    };

    // Выводим информацию о Hub и его сенсорах
    println!("{:#?}", hub);
}

При создании экземпляра структуры можно не указывать тип, rust возьмет его вывод на себя, но это не всегда работает.

Я специально создал строку несколькими доступными способами. Если задать строку как “Room 101” это не будет являться строкой типа String, это будет строка типа str - строковый срез. Частая ошибка начинающих путать типы строк, но со временем привыкаешь.

Вывод:

Hub {
    name: "Main Hub",
    id: "HUB001",
    location: "Room 101",
    sensors: [],
}

Шаг 3. Сенсоры
#

Настало время добавить сенсоры.

fn main() {
    // Создаем сенсоры
    let sensor1 = Sensor {
        name: "Temperature Sensor".to_string(),
        id: "TEMP001".to_string(),
        sensor_type: "Temperature".to_string(),
        value: 25.3,
        unit: "°C".to_string(),
        is_active: true,
    };

    let sensor2 = Sensor {
        name: "Humidity Sensor".to_string(),
        id: "HUM001".to_string(),
        sensor_type: "Humidity".to_string(),
        value: 60.5,
        unit: "%".to_string(),
        is_active: true,
    };

     // Создаем хаб и добавляем сенсоры
    let hub = Hub {
        name: "Main Hub".to_string(),
        id: String::from("HUB001"),
        location: "Room 101".to_string(),
        sensors: vec![sensor1, sensor2],
    };

    // Выводим информацию о хабе и его сенсорах
    println!("{:#?}", hub);
}

Новые сенсоры замечательно расположились над хабом, а затем нехитрым образом были добавлены к нему.

В Rust используется макрос vec! для создания массива.

С макросами мы уже немного знакомы: макрос println! - вывод на консоль.

В квадратных скобках указываются значения массива. Есть вторая форма этого макроса: vec![1; 3] создаст массив из 3-x единиц [1, 1, 1]

Подробнее про макрос vec! - https://doc.rust-lang.org/std/macro.vec.html

Вывод программы:

Hub {
    name: "Main Hub",
    id: "HUB001",
    location: "Room 101",
    sensors: [
        Sensor {
            name: "Temperature Sensor",
            id: "TEMP001",
            sensor_type: "Temperature",
            value: 25.3,
            unit: "°C",
            is_active: true,
        },
        Sensor {
            name: "Humidity Sensor",
            id: "HUM001",
            sensor_type: "Humidity",
            value: 60.5,
            unit: "%",
            is_active: true,
        },
    ],
}

Заключение
#

Надеюсь, эта статья была полезной и вы узнали что-то новое о работе с языком Rust а также его структурами. Увидимся и в следующей заметке мы рассмотрим, как добавлять методы к структурам.

about-rust - Эта статья часть цикла.
Часть 4: Эта статья

Связанные статьи

Rust императивный и функциональный, а также о методе collect
1030 слов·5 минут· loading · loading
Rust Dev
Basic rust
326 слов·2 минут· loading · loading
Rust Dev
Pattern matсhing
606 слов·3 минут· loading · loading
Rust Dev