Введение в Rust: почему стоит начать прямо сейчас
Rust — это язык системного программирования, который сочетает производительность C++ с безопасностью памяти, гарантированной на уровне компилятора. В 2025 году Rust продолжает активно развиваться: его используют в ядре Linux, браузере Firefox, инструментах командной строки и даже в веб-разработке (через WebAssembly). Если вы до сих пор не попробовали Rust, сейчас самое время — сообщество стало дружелюбнее, инструментарий — удобнее, а документация — ещё полнее.
В этой статье мы пройдём путь от установки до написания осмысленной программы. Вы узнаете, как настроить окружение, написать первый код, разобраться с ключевыми концепциями (владение, заимствование, lifetimes) и сразу применить их на практике. К концу статьи у вас будет работающий проект и понимание, куда двигаться дальше.
1. Установка Rust и настройка окружения
1.1. Установка через rustup
Самый простой способ установить Rust — использовать официальный инструмент rustup. Он управляет версиями компилятора и позволяет легко обновляться. Откройте терминал и выполните команду:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
После установки перезагрузите терминал или выполните source $HOME/.cargo/env. Проверьте, что всё работает:
rustc --version
cargo --version
Вы должны увидеть что-то вроде rustc 1.78.0 (2024-05-02) — версия может отличаться, но главное, что команды выполняются без ошибок.
1.2. Что такое Cargo?
Cargo — это менеджер пакетов и система сборки для Rust. Он автоматически скачивает зависимости, компилирует код и управляет проектами. Вам не придётся вручную вызывать rustc — Cargo сделает всё за вас.
1.3. Редакторы и IDE
Для комфортной работы рекомендую использовать:
- VS Code с расширением
rust-analyzer— автодополнение, проверка ошибок, рефакторинг. - IntelliJ IDEA с плагином Rust — мощный инструмент, но требует больше ресурсов.
- Vim/Neovim с coc-rust-analyzer — для консольных разработчиков.
После установки расширения откройте папку с проектом — rust-analyzer автоматически подхватит настройки.
2. Пишем первую программу на Rust
2.1. Создание проекта через Cargo
Создадим новый проект:
cargo new hello_rust
cd hello_rust
Команда cargo new создаёт папку с файлом Cargo.toml (манифест проекта) и подпапкой src с файлом main.rs. Откройте src/main.rs — там уже есть шаблон:
fn main() {
println!("Hello, world!");
}
Запустите программу:
cargo run
Вы увидите Hello, world! в консоли. Поздравляю — вы только что скомпилировали и выполнили свою первую программу на Rust!
2.2. Разбор структуры кода
fn main()— точка входа в программу. Все программы на Rust начинаются с этой функции.println!— макрос для вывода текста в консоль. Восклицательный знак отличает макрос от обычной функции.- Строка заканчивается точкой с запятой — это обязательно (кроме выражений, возвращающих значение).
3. Основные концепции Rust: переменные, типы и управление памятью
3.1. Переменные и неизменяемость
В Rust переменные по умолчанию неизменяемы. Это не баг, а фича — так компилятор гарантирует, что данные не изменятся случайно. Чтобы сделать переменную изменяемой, используйте ключевое слово mut:
fn main() {
let x = 5; // неизменяемая
// x = 6; // ОШИБКА: cannot assign twice to immutable variable
let mut y = 10; // изменяемая
y = 20; // OK
println!("x = {}, y = {}", x, y);
}
3.2. Типы данных
Rust — строго типизированный язык, но компилятор часто выводит тип сам. Основные типы:
i32,u32,i64— целые числа со знаком и без.f64— числа с плавающей точкой (по умолчанию).bool— логический тип (true/false).char— один символ Юникода.String— изменяемая строка из кучи.&str— строковый срез (неизменяемая ссылка на строку).
Пример:
fn main() {
let guess: u32 = "42".parse().expect("Не число");
let pi: f64 = 3.1415;
let letter: char = 'R';
let name: String = String::from("Rust");
let greeting: &str = "Привет";
println!("{} {}", greeting, name);
}
3.3. Владение (Ownership) — сердце Rust
Владение — это набор правил, которые управляют памятью без сборщика мусора. Три правила:
- У каждого значения в Rust есть один владелец.
- Когда владелец выходит из области видимости, значение удаляется.
- Значение можно либо переместить (move), либо одолжить (borrow).
Пример перемещения:
fn main() {
let s1 = String::from("hello");
let s2 = s1; // s1 перемещается в s2
// println!("{}", s1); // ОШИБКА: s1 больше не владеет значением
println!("{}", s2); // OK
}
Пример заимствования (borrowing):