Язык программирования 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 идёт туда, где важны и скорость, и надёжность, а падение стоит дорого. Под каждой сферой — известные проекты и продукты, где он работает.
-
01
Системное ПО
Ядра операционных систем и драйверы — код, где одна ошибка памяти превращается в уязвимость.
-
02
Сетевая инфраструктура
Прокси, балансировщики и виртуализация: предсказуемые задержки без пауз сборщика мусора.
-
03
Инструменты разработчика
Сборщики, линтеры, менеджеры пакетов и редакторы, которые в разы быстрее предшественников.
-
04
Базы данных и поиск
Движки хранения, векторные базы и поиск: много данных и много параллельной работы.
-
05
Браузеры и WebAssembly
Части браузерных движков и тяжёлый код для браузера, собранный в WebAssembly.
-
06
Встраиваемые устройства
Прошивки микроконтроллеров без операционной системы: без среды исполнения и скрытых выделений памяти.
-
07
Десктопные приложения
Лёгкие кроссплатформенные приложения, быстрые родные редакторы и терминалы.
-
08
Данные и ИИ
Быстрые таблицы данных, токенизаторы и запуск моделей — часто как движок под Python-интерфейсом.
Плюсы и минусы 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 выбирают чаще всего. Точные цифры зависят от задачи и кода, поэтому в таблице — взаимное положение, а не бенчмарки.
| Критерий | Rust | C++ | C | Go | Java | Python |
|---|---|---|---|---|---|---|
| Память | владение, проверяет компилятор | вручную и умные указатели | вручную | сборщик мусора | сборщик мусора | сборщик мусора |
| Безопасность памяти | гарантирована вне 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: где он упирается
-
Код, который меняется каждый день
Каждая переделка заново проходит проверку заимствований. Для экспериментов и прототипов на выброс строгость стоит дороже, чем экономит.
-
Графы и циклические структуры
Двусвязные списки, графы с обратными ссылками и «наблюдатели» не ложатся на владение. Их строят на индексах, аренах или
RcиRefCell. -
Async привязан к одной среде
Большинство асинхронных крейтов рассчитаны на Tokio. Сменить или смешать среды больно — без причины берите Tokio с самого начала.
-
Время сборки в CI
Чистая сборка большого проекта идёт минутами. Время срезают кеш, рабочие пространства,
cargo checkв редакторе и быстрый линкер. -
Глубокая связка с C++
Вызвать C просто, но шаблоны и классы C++ на Rust не ложатся. Мосты вроде cxx помогают, но смешанная кодовая база остаётся дорогой.
-
Плагины и динамические библиотеки
Без стабильного ABI плагин нужно собирать тем же компилятором или связывать через интерфейс C — сложнее, чем в C, Go или Java.
8 советов, как писать на Rust без шишек
-
01
Дочитывайте ошибки компилятора
В сообщении обычно уже есть исправление: что одолжить, где добавить
moveилиclone(). Это лучший учитель, который есть у языка. -
02
Поначалу клонируйте без стыда
Лишний
clone()стоит микросекунды, неделя борьбы с временем жизни — неделю. Сначала заставьте работать, потом замерьте, потом оптимизируйте. -
03
thiserror в библиотеках, anyhow в приложениях
Библиотека возвращает точные типы ошибок, приложение собирает их с контекстом. Остальное делает
?. -
04
Clippy и rustfmt в CI
cargo clippy -- -D warningsнаходит сотни неидиоматичных мест и настоящие ошибки,cargo fmt --checkзакрывает споры о стиле. -
05
unsafe — мало и с объяснением
Прячьте его за безопасной функцией и пишите комментарий
// SAFETY:— почему гарантии соблюдены. Ревьюеры читают эти блоки первыми. -
06
Async — только для ввода-вывода
Async окупается на множестве сетевых соединений. Для тяжёлых вычислений проще и быстрее потоки или Rayon.
-
07
Ускорьте сборку
cargo checkво время правок, рабочее пространство из небольших крейтов, кеш сборки в CI и быстрый линкер вроде mold. -
08
Замер перед оптимизацией
Бенчмарки criterion и flame graph показывают, куда уходит время. Rust быстрый по умолчанию — выигрыш обычно в алгоритме.
Как выглядит Rust: 3 примера кода
Три коротких примера к главным идеям Rust: владение, типы, которые покрывают все случаи, и безопасная параллельность. Каждый собирается одной стандартной библиотекой: rustc 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 обязан разобрать все варианты, а ? передаёт ошибку наверх без исключений.
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}"),
}
}
}
Безопасная параллельность
Четыре потока суммируют свои части одного массива. Потоки с областью видимости безопасно одалживают данные, а гонка между потоками просто не скомпилируется.
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 — скажу честно и помогу найти правильное решение. Расскажите о проекте — отвечу в течение рабочего дня.