Язык программирования Rust: полный обзор, плюсы, минусы и пределы

Для чего нужен язык программирования Rust, где он лучший выбор, а где выигрывает другой: безопасная память без сборщика мусора, плюсы и минусы, сравнение с C++, C, Go, Java и Python, примеры кода, экосистема, пределы и советы.

Стек и технологии Обновлено

Коротко

Rust — компилируемый системный язык программирования, который даёт скорость C и C++ без их ошибок работы с памятью. Вместо сборщика мусора у него владение и заимствование: компилятор проверяет каждое обращение к памяти и не пропускает код с висячими указателями и гонками данных. Rust берут для системного ПО, сетевой инфраструктуры, инструментов разработчика, баз данных, WebAssembly и встраиваемых устройств — сегодня он есть в ядре Linux, Android, Windows, Firefox и Cloudflare. Плата — крутой порог входа, медленная компиляция и больше усилий на быстрых прототипах.

Rust коротко: паспорт языка

Главные факты одной таблицей: откуда язык взялся, как он управляет памятью и как развивается.

Автор
Грейдон Хоар, личный проект 2006 года; с 2009 года его поддерживала Mozilla
Выход
Rust 1.0 — май 2015 года
Управление
Rust Foundation с 2021 года: AWS, Google, Huawei, Microsoft, Mozilla и другие
Типизация
Статическая и строгая, с выводом типов; перечисления с данными и сопоставление с образцом
Исполнение
Компиляция в машинный код через LLVM, на выходе — один бинарный файл
Память
Владение и заимствование, без сборщика мусора; проверяется при компиляции
Конкурентность
Потоки и async/await; гонки данных отсекает компилятор
Ошибки
Result и Option вместо исключений и null, оператор ?
Релизы
Каждые шесть недель; редакции раз в три года: 2015, 2018, 2021, 2024
Совместимость
Стабильные версии не ломают код; каждый пакет переходит на новую редакцию сам
Инструменты
Cargo — сборка, зависимости, тесты и документация; rustfmt, Clippy, rust-analyzer
Платформы
Linux, macOS, Windows; x86, ARM, RISC-V; микроконтроллеры; WebAssembly

Для чего применяется Rust: 8 сфер

Rust идёт туда, где важны и скорость, и надёжность, а падение стоит дорого. Под каждой сферой — известные проекты и продукты, где он работает.

  1. 01

    Системное ПО

    Ядра операционных систем и драйверы — код, где одна ошибка памяти превращается в уязвимость.

    LinuxAndroidWindows

  2. 02

    Сетевая инфраструктура

    Прокси, балансировщики и виртуализация: предсказуемые задержки без пауз сборщика мусора.

    PingoraFirecrackerLinkerd

  3. 03

    Инструменты разработчика

    Сборщики, линтеры, менеджеры пакетов и редакторы, которые в разы быстрее предшественников.

    ripgrepuvRuffZed

  4. 04

    Базы данных и поиск

    Движки хранения, векторные базы и поиск: много данных и много параллельной работы.

    TiKVQdrantMeilisearch

  5. 05

    Браузеры и WebAssembly

    Части браузерных движков и тяжёлый код для браузера, собранный в WebAssembly.

    FirefoxServoWasmtime

  6. 06

    Встраиваемые устройства

    Прошивки микроконтроллеров без операционной системы: без среды исполнения и скрытых выделений памяти.

    Embassyprobe-rsTock

  7. 07

    Десктопные приложения

    Лёгкие кроссплатформенные приложения, быстрые родные редакторы и терминалы.

    TauriAlacrittyZed

  8. 08

    Данные и ИИ

    Быстрые таблицы данных, токенизаторы и запуск моделей — часто как движок под Python-интерфейсом.

    PolarstokenizersCandle

Плюсы и минусы Rust

Rust переносит работу со времени выполнения на время компиляции. Отсюда и его надёжность, и большая часть сложности.

Плюсы · 8

  • Безопасная память без сборщика

    Обращение к освобождённой памяти, двойное освобождение и разыменование null ловит компилятор. Google сообщает, что ошибок памяти в Android стало резко меньше, когда новый код пошёл на Rust.

  • Скорость C и C++

    Машинный код, ни сборщика мусора, ни среды исполнения: производительность на уровне C++, задержки предсказуемы.

  • Бесстрашная параллельность

    Система типов знает, какие данные можно передавать между потоками. Гонка данных — ошибка компиляции, а не баг на проде.

  • Выразительные типы

    Перечисления с данными, match с проверкой всех вариантов, Option вместо null. Многие правила предметной области можно записать так, что неверное состояние не соберётся.

  • Cargo и crates.io

    Сборка, зависимости, тесты, бенчмарки и документация одним инструментом — один из лучших менеджеров пакетов среди языков.

  • Понятные ошибки компилятора

    Ошибка показывает точное место, объясняет причину и часто предлагает исправление. Компилятор учит языку по ходу работы.

  • Абстракции без накладных расходов

    Итераторы, дженерики и замыкания компилируются в тот же код, что написали бы руками на C.

  • Дружит с другими языками

    Интерфейс C, WebAssembly, модули для Python через PyO3 и для Node через napi-rs: Rust ускоряет горячие места готовых продуктов.

Минусы · 8

  • Крутой порог входа

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

  • Медленная компиляция

    Проверки и оптимизации требуют времени: большие проекты собираются минутами, а папка сборки разрастается до гигабайтов.

  • Сложная асинхронность

    Встроенной среды для async нет: её выбирают сами (почти всегда Tokio), а Pin, время жизни в futures и асинхронные трейты осваиваются долго.

  • Медленно для прототипов

    Компилятор требует правильности сразу. Когда идея меняется каждый день, на Python, TypeScript или Go доехать быстрее.

  • Молодые GUI и игры

    Tauri, egui, Slint и Bevy хороши, но молоды: по сравнению с Qt или Unity меньше готовых компонентов и учебников.

  • Меньше разработчиков

    Rust-разработчиков меньше, и они дороже, чем специалисты по Go, Java или JavaScript. Для команды, которой расти, это важно.

  • unsafe требует дисциплины

    Низкоуровневый код и вызовы C уходят в блоки unsafe, где гарантии — на вас. Чем их меньше, тем лучше.

  • Нет стабильного ABI

    Библиотеки на Rust нельзя раздавать готовыми бинарниками между версиями компилятора — плагины и динамические библиотеки идут через интерфейс C.

Rust и другие языки: сравнение с C++, C, Go, Java и Python

Качественное сравнение с языками, с которыми Rust выбирают чаще всего. Точные цифры зависят от задачи и кода, поэтому в таблице — взаимное положение, а не бенчмарки.

КритерийRustC++CGoJavaPython
Память владение, проверяет компилятор вручную и умные указатели вручную сборщик мусора сборщик мусора сборщик мусора
Безопасность памяти гарантирована вне unsafe на разработчике на разработчике да да да
Скорость самая высокая самая высокая самая высокая высокая высокая низкая
Паузы и задержки без пауз без пауз без пауз короткие паузы сборщика паузы сборщика, настраиваются интерпретатор и сборщик
Параллельность потоки и async, гонки ловит компилятор потоки, гонки — на разработчике потоки, гонки — на разработчике горутины, детектор гонок в тестах потоки и виртуальные потоки мешает GIL
Время сборки медленное медленное быстрое очень быстрое среднее не нужна
Пакеты Cargo, crates.io CMake, vcpkg, Conan — единого стандарта нет стандарта нет go modules Maven, Gradle pip, uv, PyPI
Порог входа высокий очень высокий средний низкий средний самый низкий
Сильнее всего в безопасном системном ПО, скорости без сборщика играх, движках, унаследованных системах микроконтроллерах, ядрах сетевых сервисах, инфраструктуре крупных корпоративных системах данных, ML, скриптах

Когда брать Rust, а когда нет

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

  • Прокси, шлюзы, высоконагруженные сетевые сервисы

    Лучший выбор

    Скорость без пауз сборщика и никаких ошибок памяти в коде, который смотрит в интернет.

  • Консольные утилиты

    Лучший выбор

    Один быстрый бинарник, мгновенный старт; с clap интерфейс собирается легко.

  • Горячее место продукта

    Лучший выбор

    Парсеры, сжатие, обработка изображений — медленную часть переписывают на Rust и вызывают из Python или Node.

  • WebAssembly в браузере

    Лучший выбор

    Компактные модули без среды исполнения и зрелые инструменты: wasm-bindgen, wasm-pack.

  • Прошивки микроконтроллеров

    Лучший выбор

    no_std, Embassy и probe-rs: безопасность там, где отладка труднее всего.

  • Базы данных и движки хранения

    Лучший выбор

    Контроль над памятью и параллельностью без гонок данных.

  • Бэкенд и API веб-сервиса

    Подходит

    Axum и Actix Web быстрые и надёжные, но на Go или TypeScript тот же сервис обычно выходит раньше.

  • Десктопные приложения

    Подходит

    Tauri даёт лёгкие приложения с веб-интерфейсом; родные GUI-библиотеки пока молоды.

  • Игры

    Подходит

    Bevy быстро растёт, но для коммерческой игры надёжнее Unity, Unreal или Godot.

  • Контентный сайт или интернет-магазин

    Другой язык

    Готовая CMS, PHP или генератор статики — Rust тут ничего не даёт, кроме затрат.

  • MVP, который меняется каждую неделю

    Другой язык

    Python, TypeScript или Go: скорость изменений важнее скорости кода.

  • Обучение ML-моделей

    Другой язык

    Python и его библиотеки; Rust годится как движок под ними.

  • Интерфейсы мобильных приложений

    Другой язык

    Swift, Kotlin или Flutter; Rust может жить внутри как общее ядро.

Экосистема Rust: библиотеки для частых задач

Стандартная библиотека Rust нарочно небольшая: HTTP, JSON и базы данных живут в крейтах — так в Rust называют пакеты. Вот с каких начинает большинство проектов.

ЗадачаСтандартная библиотекаПопулярные крейты
Среда для async std::future Tokio, smol
HTTP-сервер — Axum, Actix Web, Rocket
HTTP-клиент — reqwest, hyper
JSON и сериализация — Serde, serde_json
Базы данных — SQLx, Diesel, SeaORM
Консольный интерфейс std::env clap
Логи и трассировка — tracing, log
Ошибки std::error::Error thiserror, anyhow
Параллельные вычисления std::thread Rayon
Тесты и бенчмарки #[test], cargo test proptest, insta, criterion
WebAssembly — wasm-bindgen, wasm-pack
Десктоп и GUI — Tauri, egui, Slint, iced
Микроконтроллеры core (no_std) Embassy, probe-rs
Модули для Python и Node — PyO3, maturin, napi-rs

Пределы Rust: где он упирается

  1. Код, который меняется каждый день

    Каждая переделка заново проходит проверку заимствований. Для экспериментов и прототипов на выброс строгость стоит дороже, чем экономит.

  2. Графы и циклические структуры

    Двусвязные списки, графы с обратными ссылками и «наблюдатели» не ложатся на владение. Их строят на индексах, аренах или Rc и RefCell.

  3. Async привязан к одной среде

    Большинство асинхронных крейтов рассчитаны на Tokio. Сменить или смешать среды больно — без причины берите Tokio с самого начала.

  4. Время сборки в CI

    Чистая сборка большого проекта идёт минутами. Время срезают кеш, рабочие пространства, cargo check в редакторе и быстрый линкер.

  5. Глубокая связка с C++

    Вызвать C просто, но шаблоны и классы C++ на Rust не ложатся. Мосты вроде cxx помогают, но смешанная кодовая база остаётся дорогой.

  6. Плагины и динамические библиотеки

    Без стабильного ABI плагин нужно собирать тем же компилятором или связывать через интерфейс C — сложнее, чем в C, Go или Java.

8 советов, как писать на Rust без шишек

  1. 01

    Дочитывайте ошибки компилятора

    В сообщении обычно уже есть исправление: что одолжить, где добавить move или clone(). Это лучший учитель, который есть у языка.

  2. 02

    Поначалу клонируйте без стыда

    Лишний clone() стоит микросекунды, неделя борьбы с временем жизни — неделю. Сначала заставьте работать, потом замерьте, потом оптимизируйте.

  3. 03

    thiserror в библиотеках, anyhow в приложениях

    Библиотека возвращает точные типы ошибок, приложение собирает их с контекстом. Остальное делает ?.

  4. 04

    Clippy и rustfmt в CI

    cargo clippy -- -D warnings находит сотни неидиоматичных мест и настоящие ошибки, cargo fmt --check закрывает споры о стиле.

  5. 05

    unsafe — мало и с объяснением

    Прячьте его за безопасной функцией и пишите комментарий // SAFETY: — почему гарантии соблюдены. Ревьюеры читают эти блоки первыми.

  6. 06

    Async — только для ввода-вывода

    Async окупается на множестве сетевых соединений. Для тяжёлых вычислений проще и быстрее потоки или Rayon.

  7. 07

    Ускорьте сборку

    cargo check во время правок, рабочее пространство из небольших крейтов, кеш сборки в CI и быстрый линкер вроде mold.

  8. 08

    Замер перед оптимизацией

    Бенчмарки criterion и flame graph показывают, куда уходит время. Rust быстрый по умолчанию — выигрыш обычно в алгоритме.

Как выглядит Rust: 3 примера кода

Три коротких примера к главным идеям Rust: владение, типы, которые покрывают все случаи, и безопасная параллельность. Каждый собирается одной стандартной библиотекой: rustc main.rs.

Владение и заимствование

У значения один владелец. Его можно одолжить по ссылке, а после передачи владения старое имя использовать нельзя — это проверяет компилятор ещё до запуска.

main.rs
fn main() {
    let title = String::from("Rust");
    let len = count(&title); // одалживаем строку: владелец остаётся прежним
    println!("{title}: {len}");

    let moved = title; // владение переходит к moved
    // println!("{title}"); // ошибка компиляции: title больше не владеет строкой
    println!("{moved}");
}

fn count(s: &str) -> usize {
    s.chars().count()
}

Перечисления, match и ошибки

Перечисление несёт данные, match обязан разобрать все варианты, а ? передаёт ошибку наверх без исключений.

main.rs
use std::num::ParseIntError;

#[derive(Debug)]
enum Plan {
    Free,
    Pro { seats: u32 },
}

fn price(plan: &Plan) -> u32 {
    match plan {
        // компилятор проверит, что разобраны все варианты
        Plan::Free => 0,
        Plan::Pro { seats } => 12 * seats,
    }
}

fn parse_plan(input: &str) -> Result<Plan, ParseIntError> {
    let seats: u32 = input.trim().parse()?; // ? вернёт ошибку наверх
    Ok(if seats == 0 { Plan::Free } else { Plan::Pro { seats } })
}

fn main() {
    for input in ["3", "0", "три"] {
        match parse_plan(input) {
            Ok(plan) => println!("{plan:?}: ${}", price(&plan)),
            Err(e) => println!("«{input}» — не число: {e}"),
        }
    }
}

Безопасная параллельность

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

main.rs
use std::thread;

fn main() {
    let numbers: Vec<u64> = (1..=1_000_000).collect();

    // четыре потока считают свои части; делить данные небезопасно компилятор не даст
    let total: u64 = thread::scope(|s| {
        let handles: Vec<_> = numbers
            .chunks(numbers.len() / 4)
            .map(|chunk| s.spawn(move || chunk.iter().sum::<u64>()))
            .collect();
        handles.into_iter().map(|h| h.join().unwrap()).sum()
    });

    println!("сумма: {total}"); // 500000500000
}

Вопросы о Rust

Что такое Rust простыми словами?

Язык программирования со скоростью C и C++, в котором компилятор не даёт совершить большинство ошибок с памятью и потоками. На нём пишут системное ПО, инфраструктуру, инструменты и всё, где падение обходится дорого.

Почему Rust называют безопасным?

Владение и заимствование позволяют компилятору доказать, что память не используется после освобождения, а потоки не гоняются за одни и те же данные. Вне блоков unsafe такие ошибки не компилируются.

Есть ли в Rust сборщик мусора?

Нет. Память освобождается ровно тогда, когда её владелец выходит из области видимости, — это решается при компиляции. Поэтому нет пауз и задержки предсказуемы.

Rust или Go?

Go проще выучить и быстрее на нём писать, у него сборщик мусора — хорошо для сетевых сервисов и команд, которым важен темп. Rust даёт максимум скорости без пауз и более строгие гарантии, но порог входа у него выше.

Rust или C++?

Для нового системного кода Rust обычно надёжнее: скорость та же, ошибки памяти ловит компилятор, один инструмент сборки. C++ остаётся там, где большая готовая кодовая база, игровые движки или библиотеки, которые есть только на C++.

Сложно ли выучить Rust?

Сложнее, чем Go или Python: владение и время жизни требуют времени. Официальная книга «The Rust Programming Language» и подробные сообщения компилятора заметно сокращают путь.

Подходит ли Rust для веб-разработки?

Для быстрых и надёжных API и сервисов — да, с Axum или Actix Web, а для тяжёлого кода в браузере — через WebAssembly. Для обычных сайтов и быстрых продуктов PHP, TypeScript или Go обычно доезжают раньше.

Кто использует Rust?

Код на Rust работает в ядре Linux, Android и Windows, в Firefox, сети Cloudflare, виртуальных машинах AWS Lambda (Firecracker), в Discord, Dropbox и Figma, а также в популярных инструментах uv, Ruff и Zed.

Форма

Быстрые
сервисы

Пишу нагруженные сервисы на Go — он закрывает большинство задач, ради которых смотрят на Rust. Если задаче действительно нужен Rust — скажу честно и помогу найти правильное решение. Расскажите о проекте — отвечу в течение рабочего дня.

Или пишите на [email protected]