惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
C
CXSECURITY Database RSS Feed - CXSecurity.com
L
LINUX DO - 热门话题
S
Secure Thoughts
TaoSecurity Blog
TaoSecurity Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
T
Threat Research - Cisco Blogs
AI
AI
B
Blog RSS Feed
S
Schneier on Security
雷峰网
雷峰网
Schneier on Security
Schneier on Security
Help Net Security
Help Net Security
Cloudbric
Cloudbric
L
LINUX DO - 最新话题
罗磊的独立博客
有赞技术团队
有赞技术团队
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Apple Machine Learning Research
Apple Machine Learning Research
P
Proofpoint News Feed
酷 壳 – CoolShell
酷 壳 – CoolShell
The Hacker News
The Hacker News
博客园 - Franky
Attack and Defense Labs
Attack and Defense Labs
The Cloudflare Blog
Webroot Blog
Webroot Blog
Last Week in AI
Last Week in AI
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
博客园 - 叶小钗
美团技术团队
L
Lohrmann on Cybersecurity
T
The Blog of Author Tim Ferriss
The Last Watchdog
The Last Watchdog
T
Troy Hunt's Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Vercel News
Vercel News
Know Your Adversary
Know Your Adversary
O
OpenAI News
博客园 - 【当耐特】
Hacker News - Newest:
Hacker News - Newest: "LLM"
C
Cybersecurity and Infrastructure Security Agency CISA
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
www.infosecurity-magazine.com
www.infosecurity-magazine.com
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
PCI Perspectives
PCI Perspectives
H
Heimdal Security Blog
I
InfoQ
GbyAI
GbyAI
T
Threatpost
C
Cisco Blogs

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Rust: зачем он появился, что умеет и почему компании переписывают на него части своих систем
DevRoad · 2026-05-07 · via Все публикации подряд на Хабре

Эта статья — для тех, кто только присматривается к Rust или слышал о нем лишь обрывки восторженных или невосторженных отзывов. Если вы не до конца понимаете, зачем миру понадобился еще один системный язык, какие «боли» C++ он лечит и где реально используется сегодня, — здесь вы найдете ответы на эти вопросы. Мы постарались структурированно представить информацию, чтобы у вас сложилась полная картина: что это за язык, зачем его учить и с чего начать освоение. Сразу оговоримся: если «The Book» давно стала вашей настольной книгой, вы уже собаку съели на управлении памятью и знаете все о владении и заимствовании, эта статья вряд ли вас удивит. Остальным же — добро пожаловать.

В апреле 2026 года произошло сразу два события, заставивших вновь говорить о Rust. 16 апреля вышел очередной стабильный релиз — Rust 1.95.0. А вскоре после этого Илон Маск заявил, что новый мессенджер XChat построен на Rust и «whole new architecture».

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

Что такое Rust, если объяснить в одном абзаце

Rust — это системный язык программирования, созданный для разработки высокопроизводительного и отказоустойчивого софта. Он компилируется в машинный код, не требует виртуальной машины вроде JVM и не использует сборщик мусора как Java, Go, JavaScript или Python.

Главная особенность Rust — безопасность памяти без garbage collector. То есть язык старается не допустить use-after-free, dangling pointer, double free, data race и другие неприятности еще на этапе компиляции.

Если совсем коротко:

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

Почему Rust вообще появился

Rust был создан Грейдоном Хоаром в Mozilla в период с 2006 по 2010 год. Хоар работал над языком в личное время, а затем Mozilla поддержала проект как перспективную платформу для разработки браузерных движков. Стабильная версия Rust 1.0 вышла 15 мая 2015 года.

Уже тогда команда формулировала задачу языка довольно четко: помочь строить надежные и эффективные системы, сочетая низкоуровневый контроль с высокоуровневыми гарантиями безопасности — без обязательного garbage collector и runtime.

Чтобы понять, зачем Rust был нужен, нужно вспомнить реальность системного программирования. Огромная часть критически важного ПО десятилетиями писалась на C и C++: браузеры, ядра ОС, драйверы, базы данных, сетевые сервисы. Эти языки невероятно мощные, но они дают разработчику очень много свободы. А свобода в работе с памятью часто означает, что программа может сделать что-то опасное.

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

Chromium Project писал, что около 70% high severity security bugs в Chromium были memory unsafety problems, то есть ошибками работы с C/C++ pointers. Половина из них — use-after-free. Это не “70% всех багов Chrome”, а именно серьезные security bugs, но цифра все равно очень показательная.

Rust появился как попытка закрыть эту инженерную дыру:

  • дать производительность уровня C/C++;

  • убрать значительную часть ошибок памяти;

  • не вводить GC;

  • сделать современный toolchain (менеджер пакетов, тестирование, документация);

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

Короткая формула:

Rust появился не потому, что миру не хватало еще одного языка программирования. Он появился потому, что у старых подходов был болезненный компромисс: либо быстро, но опасно; либо безопаснее, но с runtime, GC и меньшим контролем.

Какие проблемы других языков Rust пытался решить

Чтобы понять ценность Rust, нужно посмотреть на недостатки существующих языков.

C/C++: быстро, но опасно

C и C++ дают почти максимальный контроль над памятью. Разработчик сам решает, где и когда выделять память, когда освобождать, как передавать указатели, как работать с буферами.

Это делает C/C++ быстрыми и гибкими. Но цена — высокая вероятность ошибок.

Основные проблемы:

  • Memory safety (безопасность работы с памятью) полностью лежит на плечах разработчика.

  • Buffer overflow и buffer over-read — запись или чтение за пределами выделенного буфера.

  • Use-after-free — использование указателя после освобождения памяти.

  • Double free — повторное освобождение одной и той же области памяти.

  • Dangling pointer — указатель, который больше не указывает на валидный объект.

Пример на C:

#include <stdio.h>
#include <string.h>

int main() {
    char name[8];

    strcpy(name, "very very long name");

    printf("%s\n", name);
    return 0;
}

Здесь массив name рассчитан на 8 символов, но мы записываем туда строку сильно длиннее. В C это может привести к повреждению памяти. Иногда программа просто упадет. Иногда будет вести себя странно. Иногда такая ошибка станет частью exploit chain.

Rust не разрешает такой стиль работы в safe-коде. Например, если мы работаем с вектором, доступ по индексу проверяется:

fn main() {
    let items = vec![1, 2, 3];

    // println!("{}", items[10]); // panic: индекс вне границ
    println!("{:?}", items.get(10)); // None
}

items[10] приведtт к panic, потому что индекс вне границ. А items.get(10) вернет None, то есть безопасно скажет: “такого элемента нет”.

Хороший исторический пример — Heartbleed в OpenSSL, 2014 год. В реализации механизма heartbeat для проверки активности соединения в OpenSSL отсутствовала корректная проверка границ. Клиент мог запросить «отправь мне 500 байт», а отправить только 1 байт данных. Библиотека на C честно читала 500 байт из памяти — в том числе чужие ключи шифрования, пароли, сессионные cookie. Технически это buffer over-read (чтение за пределы), но корень тот же: отсутствие проверки границ.

Rust не делает невозможной любую уязвимость, но он резко снижает вероятность целого класса memory-safety ошибок в safe-коде.

Еще один пример — dangling pointer. В C++ можно случайно сохранить указатель на объект, который уже уничтожен:

#include <iostream>

int* make_number() {
    int value = 42;
    return &value; // опасно: возвращаем адрес локальной переменной
}

int main() {
    int* p = make_number();
    std::cout << *p << std::endl; // неопределенное поведение
}

value живет только внутри функции make_number. После выхода из функции память больше невалидна, но указатель p все еще “куда-то” указывает.

Rust такой код в safe-варианте не пропустит:

fn make_number() -> &i32 {
    let value = 42;
    &value
}

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

Это и есть одна из главных идей Rust: лучше получить ошибку компиляции, чем production-инцидент.

Java: безопаснее, но есть JVM и GC

Java решила многие проблемы C/C++ другим способом. Разработчик не освобождает память вручную. Этим занимается garbage collector — сборщик мусора.

  • JVM — Java Virtual Machine, виртуальная машина, внутри которой выполняется Java-программа.

  • Runtime — дополнительное программное обеспечение, которое работает параллельно с программой и управляет ее выполнением.

  • GC — garbage collector, механизм автоматического удаления объектов, которые больше не используются.

  • Pause time — паузы, которые могут возникать из-за работы GC. Самый заметный тип таких пауз — Stop-the-world (STW): моменты, когда JVM временно приостанавливает выполнение потоков приложения, чтобы выполнить часть работы сборщика мусора.

Для enterprise/backend Java — прекрасный выбор. Она зрелая, стабильная, с огромной экосистемой. Но для драйверов, ядра ОС, embedded, криптографии, некоторых low-latency систем и очень чувствительных к задержкам компонентов JVM, GC и возможные STW-паузы могут быть сильным ограничением.

Например, в Java можно получить NullPointerException:

class Main {
    static String findUserName(int id) {
        if (id == 1) {
            return "Alice";
        }
        return null;
    }

    public static void main(String[] args) {
        String name = findUserName(2);
        System.out.println(name.length()); // NullPointerException
    }
}

Проблема не в том, что Java плохая. Проблема в том, что null — это особое значение, которое может оказаться почти где угодно, если API это допускает.

В Rust отсутствие значения выражается типом:

fn find_user_name(id: u32) -> Option<String> {
    if id == 1 {
        Some(String::from("Alice"))
    } else {
        None
    }
}

fn main() {
    match find_user_name(2) {
        Some(name) => println!("{}", name.len()),
        None => println!("user not found"),
    }
}

Option<T> означает: значение либо есть (Some), либо его нет (None). Компилятор заставляет обработать оба случая. Это не гарантия, что в программе не будет логических ошибок, но шанс забыть про “пустое значение” становится гораздо ниже.

Go: проще, но меньше контроля

Go — отличный язык для написания инфраструктурного кода. Он проще Rust, имеет удобный garbage collector и отличную поддержку concurrency через горутины.

Однако Go тоже использует GC, а значит, имеет паузы и меньший контроль над памятью. Кроме того, Go не предотвращает data race (гонки данных) на этапе компиляции.

Data race — ситуация, когда два потока или горутины одновременно обращаются к одним и тем же данным, и хотя бы один из них эти данные изменяет. В Go есть встроенный race detector, который запускается через -race, но он ищет гонки, проявившиеся во время выполнения тестов или программы. Rust же старается не дать написать многие такие сценарии уже на этапе компиляции.

Пример идеи на Rust:

use std::thread;

fn main() {
    let mut counter = 0;

    thread::scope(|s| {
        s.spawn(|| {
            counter += 1;
        });

        s.spawn(|| {
            counter += 1;
        });
    });

    println!("{counter}");
}

Такой код не должен компилироваться: две задачи пытаются одновременно получить изменяемый доступ к counter.

Правильный вариант — явно использовать синхронизацию:

use std::sync::{Arc, Mutex};
use std::thread;

fn main() {
    let counter = Arc::new(Mutex::new(0));

    let mut handles = vec![];

    for _ in 0..2 {
        let counter = Arc::clone(&counter);

        handles.push(thread::spawn(move || {
            let mut value = counter.lock().unwrap();
            *value += 1;
        }));
    }

    for handle in handles {
        handle.join().unwrap();
    }

    println!("{}", *counter.lock().unwrap());
}

Arc — атомарный счетчик ссылок для совместного владения между потоками.
Mutex — механизм, который разрешает доступ к данным только одному потоку за раз.

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

Python: быстро писать, но не для системного уровня

Python прекрасен для скриптов, data science, automation, backend и прототипов. Но он не создан для низкоуровневого управления памятью и предсказуемой производительности.

В реальных проектах часто встречается гибридный подход: бизнес-логика, orchestration или data science-пайплайн пишутся на Python, а performance-critical части выносятся в C, C++ или Rust.

Хороший пример направления — data processing. В экосистеме Rust есть Polars и DataFusion: быстрые инструменты обработки данных, которые часто используют как альтернативу или дополнение к Python-пайплайнам.

Как работает Rust? Основные концепции

Теперь к самому важному.

Главная идея Rust: ownership

Ownership — владение. В Rust у каждого значения есть ровно один владелец. Когда владелец выходит из области видимости, значение уничтожается, а ресурсы освобождаются. Это основной механизм, благодаря которому Rust управляет памятью без GC.

fn main() {
    let string1 = String::from("hello");
    let string2 = string1;

    // println!("{}", string1); // ошибка компиляции
    println!("{}", string2);
}

Что произошло? String хранит данные в куче. Когда мы пишем let string2 = string1, владение строкой переходит от string1 к string2. После этого string1 больше нельзя использовать.

В JavaScript, Java или Python такое поведение может показаться странным: “почему я не могу использовать старую переменную?” Но Rust делает это не из вредности. Он предотвращает ситуацию, когда две переменные считают себя владельцами одного ресурса и пытаются освободить его дважды.

Для простых типов вроде i32 все иначе:

fn main() {
    let x = 42;
    let y = x;

    println!("{x}");
    println!("{y}");
}

i32 копируется дешево, поэтому здесь работает Copy: обе переменные имеют собственное значение.

Borrowing: можно не отдавать, а одолжить

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

Заимствование — это временный доступ к значению без передачи владения.

fn main() {
    let name = String::from("Alice");

    print_name(&name);

    println!("{}", name);
}

fn print_name(value: &String) {
    println!("{}", value);
}

name владеет строкой. &name — ссылка, то есть временное заимствование. print_name не забирает строку себе. После вызова name все еще можно использовать.

Главное правило заимствования: можно иметь сколько угодно неизменяемых ссылок (&T) или одну изменяемую ссылку (&mut T), но не то и другое одновременно;

Lifetimes: ссылки не должны жить дольше данных

Lifetime — время жизни ссылки. Это период, в течение которого ссылка остается валидной.

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

fn longest<'a>(first: &'a str, second: &'a str) -> &'a str {
    if first.len() > second.len() {
        first
    } else {
        second
    }
}

'a означает: возвращаемая ссылка живет не дольше, чем входные ссылки. То есть Rust не позволит вернуть ссылку на данные, которые уже уничтожены.

Сначала lifetimes выглядят немного непонятно. Но идея простая: ссылка не должна пережить значение, на которое она указывает.

Borrow checker: строгий компилятор-друг

Borrow checker — часть компилятора Rust, которая проверяет правила владения, заимствования и времён жизни.

Новички часто воспринимают его как врага. Пишешь простой код — компилятор ругается. Передаешь значение — оно “переехало”. Берешь две mutable-ссылки — нельзя. Возвращаешь ссылку — lifetime не подходит.

Но через какое-то время становится понятно: borrow checker не мешает писать код. Он мешает писать код, о котором вы пожалеете через полгода.

Почему Rust не нужен garbage collector

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

В Rust значение уничтожается, когда выходит из области видимости:

fn main() {
    {
        let message = String::from("hello");
        println!("{}", message);
    }

    // здесь message уже уничтожен
}

Здесь message живет только внутри блока { ... }. Когда блок заканчивается, Rust вызывает деструктор и освобождает ресурсы.

Это похоже на автоматическое управление памятью, но без отдельного GC-процесса. Rust заранее проверяет, что после уничтожения значение больше не используется.

Stack и heap простыми словами

Чтобы понять Rust, полезно вспомнить разницу между stack и heap.

Stack — стек. Быстрая область памяти для локальных значений фиксированного размера. Работает по принципу LIFO: last in, first out. Функция вызвалась — ее локальные переменные появились на стеке. Функция завершилась — они исчезли.

fn sum(a: i32, b: i32) -> i32 {
    let result = a + b;
    result
}

a, b, result — простые значения, которые обычно живут на стеке.

Heap — куча. Область памяти для данных динамического размера: строк, векторов, деревьев, объектов, размер которых может быть неизвестен на этапе компиляции.

fn main() {
    let text = String::from("hello");
    let numbers = vec![1, 2, 3];
}

String и Vec хранят метаданные на стеке, а реальные данные — в куче.

Для явного размещения значения в куче есть Box<T>:

fn main() {
    let number = Box::new(10);

    println!("{}", number);
}

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

Option вместо null

В Rust нет привычного null.

Если значения может не быть, это должно быть видно в типе:

fn find_user(id: u32) -> Option<String> {
    if id == 1 {
        Some(String::from("Alice"))
    } else {
        None
    }
}

fn main() {
    let user = find_user(2);

    match user {
        Some(name) => println!("User: {}", name),
        None => println!("User not found"),
    }
}

Option<T> — это enum:

enum Option<T> {
    Some(T),
    None,
}

Самое важное: функция честно говорит вызывающему коду, что результата может не быть.

В Java вы часто узнаёте о null уже в runtime. В Rust отсутствие значения — часть модели типов, и компилятор заставляет с этим считаться.

Result вместо исключений

Rust не использует исключения как основной способ обработки ошибок. Для восстанавливаемых ошибок есть Result<T, E>.

fn divide(a: i32, b: i32) -> Result<i32, String> {
    if b == 0 {
        Err(String::from("division by zero"))
    } else {
        Ok(a / b)
    }
}

fn main() {
    match divide(10, 0) {
        Ok(value) => println!("Result: {}", value),
        Err(error) => println!("Error: {}", error),
    }
}

Result<T, E> означает: либо Ok(T), либо Err(E).

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

Для короткой передачи ошибки наверх используется оператор ?:

use std::fs;

fn read_config() -> Result<String, std::io::Error> {
    let content = fs::read_to_string("config.txt")?;
    Ok(content)
}

Если read_to_string вернёт Ok(String), строка попадет в content. Если вернет Err(std::io::Error), ошибка сразу вернется из read_config.

? заменяет типичный шаблон match Ok/Err и делает код короче без скрытых исключений.

match: не switch, а мощнее

match похож на switch, но намного сильнее. Он работает с enum, структурами, кортежами, диапазонами и шаблонами.

fn main() {
    let status = divide(10, 2);

    match status {
        Ok(value) => println!("Result: {}", value),
        Err(error) => println!("Error: {}", error),
    }
}

Если у enum есть несколько вариантов, Rust заставляет обработать все. Это снижает вероятность забыть какой-то сценарий.

Например:

enum PaymentStatus {
    Paid,
    Pending,
    Failed(String),
}

fn print_status(status: PaymentStatus) {
    match status {
        PaymentStatus::Paid => println!("paid"),
        PaymentStatus::Pending => println!("pending"),
        PaymentStatus::Failed(reason) => println!("failed: {}", reason),
    }
}

Если завтра мы добавим новый вариант Refunded, компилятор покажет места, где match больше не покрывает все варианты. Для поддержки кода это очень сильная вещь.

Traits: интерфейсы, но не совсем

trait в Rust похож на интерфейс в Java или TypeScript: он описывает поведение, которое должен реализовать тип.

trait Drawable {
    fn draw(&self);
}

struct Button {
    label: String,
}

impl Drawable for Button {
    fn draw(&self) {
        println!("Drawing button: {}", self.label);
    }
}

Теперь можно написать функцию, которая принимает все, что умеет рисоваться:

fn render(item: &impl Drawable) {
    item.draw();
}

Функции важно не то, какой конкретно тип передали, а какое поведение он умеет предоставлять.

Fearless Concurrency (бесстрашная многопоточность)

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

Zero-cost abstractions: высокоуровневый код без лишней цены

Один из принципов Rust — zero-cost abstractions.

Смысл не в том, что любая абстракция всегда бесплатна. Смысл в том, что многие удобные конструкции компилируются в машинный код без лишней runtime-стоимости по сравнению с ручным низкоуровневым вариантом.

Например, итераторы:

fn sum_even_squares(values: &[i32]) -> i32 {
    values
        .iter()
        .filter(|x| **x % 2 == 0)
        .map(|x| x * x)
        .sum()
}

Код выглядит высокоуровневым: filter, map, sum. Но компилятор может оптимизировать такую цепочку в эффективный машинный код. Операции вроде map, filter, reduce должны создавать код, столь же эффективный, как эквивалентные императивные реализации.

Unsafe Rust: если Rust безопасный, зачем ему unsafe

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

Официальная книга Rust описывает пять возможностей unsafe: разыменование raw pointer, вызов unsafe-функций, доступ или изменение mutable static, реализация unsafe trait и доступ к полям union. При этом unsafe не выключает весь borrow checker и все проверки Rust: оно только дает доступ к операциям, безопасность которых должен гарантировать сам разработчик.

Зачем это нужно? Например:

  • писать драйверы;

  • работать с C-библиотеками через FFI;

  • реализовывать низкоуровневые структуры данных;

  • писать ядро ОС;

  • оптимизировать горячие участки кода;

  • взаимодействовать с железом.

Пример raw pointer:

fn main() {
    let mut value = 10;

    let ptr = &mut value as *mut i32;

    unsafe {
        *ptr += 1;
    }

    println!("{}", value);
}

В safe Rust мы работаем со ссылками &T и &mut T. Raw pointers const T и mut T похожи на указатели C/C++, но Rust не гарантирует их безопасность. Создать raw pointer можно в safe-коде, а вот разыменование требует unsafe.

Хорошая практика: unsafe-кода должно быть мало, он должен быть изолирован и закрыт безопасным API.

Как работает Rust-программа

Rust — компилируемый язык

Rust — компилируемый язык. У него нет интерпретатора в стиле Python или JavaScript. Вы пишете код, компилятор превращает его в машинный код (через промежуточное представление LLVM), и на выходе получается готовый исполняемый файл (бинарник).

Ключевые термины:

  • компилятор — программа, которая переводит исходный код в исполняемый файл (rustc);

  • интерпретатор — программа, которая выполняет код напрямую (Python, Ruby, JS);

  • LLVM — инфраструктура компиляции, используемая Rust, Swift, Clang и другими для генерации оптимизированного кода под разные архитектуры;

  • crate — минимальная единица компиляции и базовый элемент модульной системы языка. Если проводить аналогии с другими языками, то это аналог «библиотеки» (library) или «пакета» (package). Все, что вы пишете на Rust, в конечном итоге упаковывается в крейт.

  • Cargo — система сборки и менеджер зависимостей.

Два типа крейтов

Крейты делятся на две основные категории в зависимости от их назначения:

  • Binary Crate (Бинарный крейт): Это программа, которую можно скомпилировать в исполняемый файл. Такой крейт обязательно содержит функцию main(), которая является точкой входа. Обычно основным файлом такого крейта является src/main.rs.

  • Library Crate (Библиотечный крейт): Это набор кода (функций, типов, структур), предназначенный для повторного использования в других проектах. В нем нет функции main(), и он не запускается сам по себе. Основной файл — src/lib.rs.

Cargo: почему tooling Rust так хвалят

Cargo — это package manager, build system, test runner и инструмент публикации пакетов в одном. Официальная документация Cargo описывает его как менеджер пакетов Rust, который скачивает зависимости, компилирует пакеты, делает distributable packages и загружает их на crates.io.

Для разработчика из JS-мира Cargo можно грубо представить как “npm + build tool + test runner + documentation tool”. Но в отличие от многих экосистем, здесь это стандартный путь, а не набор разрозненных решений.

Stack Overflow Developer Survey 2025 отдельно отмечает Cargo как самый admired cloud development and infrastructure tool с показателем около 71%. Rust там же снова назван самым admired programming language с показателем около 72%.

Основные команды:

  • создание нового проекта (cargo new);

  • сборка (cargo buildcargo build --release);

  • запуск (cargo run);

  • тестирование (cargo test);

  • форматирование кода (cargo fmt);

  • линтинг (cargo clippy);

  • генерация документации (cargo doc).

Crates: библиотеки Rust

Crate — пакет или библиотека в Rust.

crates.io — официальный реестр пакетов.

Rust-экосистема меньше, чем npm, Maven или PyPI, но во многих направлениях она уже очень зрелая.

Чаще всего в реальных проектах встречаются:

  • serde, serde_json — сериализация и десериализация;

  • tokio, async-std — async runtime;

  • axum, actix-web, rocket — web backend;

  • reqwest, hyper — HTTP;

  • clap — CLI-аргументы;

  • anyhow, thiserror — ошибки;

  • tracing — логирование и observability;

  • sqlx, diesel, sea-orm — базы данных;

  • wasm-bindgen, wasm-pack — WebAssembly;

  • tauri, egui — desktop/cross-platform UI;

  • polars, datafusion — обработка данных;

  • rayon — параллельные вычисления.

Итого, что предотвращает и не предотвращает Rust

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

Он предотвращает на этапе компиляции:

  • use-after-free,

  • buffer overflow/over-read (в safe-коде),

  • data race в многопоточном коде,

  • dangling pointers и т.д.

Однако важно понимать: Rust ≠ полная безопасность приложения.

Компилятор не проверит за вас:

  • криптографический протокол;

  • бизнес-логику;

  • хранение ключей;

  • privacy-модель;

  • архитектуру доступа;

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

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

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

Плюсы Rust

Главные плюсы Rust:

  • безопасность памяти без GC;

  • высокая производительность;

  • отсутствие обязательного runtime;

  • строгая система типов;

  • Option<T> вместо null;

  • Result<T, E> вместо скрытых исключений;

  • безопасная многопоточность;

  • современный tooling;

  • Cargo и crates.io;

  • хорошая совместимость с C через FFI;

  • сильные возможности для системного программирования;

  • хорошие сообщения компилятора;

  • встроенная поддержка тестирования и документации.

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

Минусы Rust

Минусы тоже реальные.

Самые заметные:

  • высокий порог входа;

  • ownership и borrowing раздражают новичков;

  • lifetimes могут быть сложными;

  • компиляция иногда долгая;

  • async Rust требует привыкания;

  • меньше библиотек, чем у Java/Node/Python в некоторых доменах;

  • меньше вакансий, чем для массовых языков;

  • не всегда подходит для быстрой продуктовой разработки;

  • unsafe-код требует дисциплины;

  • некоторые структуры данных, например графы с двунаправленными ссылками, писать сложнее, чем в языках с GC.

Rust удобен не во всем: двунаправленные ссылки, Rc, Weak, RefCell, внутренняя изменяемость и графовые структуры требуют понимания модели владения. Это не “невозможно”, но точно сложнее, чем просто хранить ссылки в языке с GC.

Почему компании переписывают части систем на Rust

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

Гораздо чаще Rust внедряют точечно: в сетевые компоненты, парсеры, sandbox, криптографию, CLI, агенты, runtime-компоненты, драйверы, сервисы с высокой нагрузкой.

Причины обычно прагматичные:

  • Снижение memory-safety рисков — меньше уязвимостей, с которыми приходится жить годами.

  • Выше надежность — Rust-код реже падает в production из-за неопределённого поведения.

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

  • Лучший контроль ресурсов — отсутствие GC позволяет точно предсказывать потребление памяти и CPU.

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

Google пишет, что в Android подход с Rust уже дал серьезный эффект: в данных 2025 года memory safety vulnerabilities впервые упали ниже 20% от общего числа уязвимостей, а Rust-код показал заметно меньшую density memory-safety уязвимостей по сравнению с C/C++.

В Linux kernel есть официальная документация по Rust внутри ядра. Это не значит, что ядро Linux переписывают на Rust целиком, но Rust стал официально поддерживаемым направлением для части kernel-разработки.

Microsoft также развивает направление Rust for Windows Drivers: в 2025 году Microsoft писала о состоянии Rust для Windows-драйверов и своём видении развития этого направления.

AWS Firecracker — пример инфраструктурного проекта, написанного на Rust: AWS описывала Firecracker как lightweight virtualization technology для serverless workloads, а в анонсах подчеркивала выбор Rust из-за thread safety и предотвращения многих buffer overrun ошибок.

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

Иными словами, Rust выбирают не потому, что он модный. Его выбирают там, где ошибка памяти, лишняя задержка или неэффективность инфраструктуры стоят дорого.

Где Rust лучше всего использовать

Rust особенно силен там, где одновременно важны скорость, надежность и контроль.

Хорошие сценарии:

  • backend и высоконагруженные сервисы;

  • API, proxy, realtime-сервисы, очереди;

  • CLI-инструменты;

  • системное программирование;

  • драйверы, ядро, низкоуровневые библиотеки;

  • embedded и IoT;

  • WebAssembly;

  • криптография и security-sensitive software;

  • парсеры;

  • data processing;

  • blockchain и инфраструктура.

Где Rust может быть плохим выбором

Rust не нужен везде.

Он может быть плохим выбором, если вы делаете MVP за два дня, простую админку, обычный CRUD-backend или продуктовую фичу, где команда гораздо сильнее в Java, Node.js, Go или Python.

Rust также может быть избыточен, если главная задача — быстро нанять команду, быстро проверить гипотезу или использовать экосистему, где Python/Java/JS дают готовые решения быстрее.

Еще один честный минус — learning curve. Ownership, borrowing и lifetimes сначала непривычны. Разработка на старте может идти медленнее. Компиляция больших проектов может занимать заметное время. Async Rust сложнее, чем async в JS или Go.

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

Rust в 2026 году: статистика

Rust уже не экспериментальный язык, но и не массовый язык уровня JavaScript, Python или Java.

По Stack Overflow Developer Survey 2025 Rust снова стал самым admired programming language с показателем около 72%, но доля worked-with среди всех респондентов — 14.8%. То есть Rust очень любят те, кто с ним работает, но он пока не стал массовым языком для всех подряд.

TIOBE Index за апрель 2026 показывает Rust в top 20, но отмечает замедление роста: после пика на #13 в начале года Rust опустился к #16. Сам TIOBE подчёркивает, что индекс показывает популярность, а не качество языка.

PYPL показывает Rust примерно в районе top 10 по tutorial/search interest: интерес к изучению сохраняется, хотя Rust не обгоняет массовые языки.

State of Rust Survey 2025, опубликованный в марте 2026 года, собрал 7156 ответов и показывает зрелое сообщество, но также фиксирует знакомые проблемы: сложность языка, ожидания вокруг compiler performance и развитие экосистемы.

Итог простой: Rust — не хайп на один сезон. Но его роль не в том, чтобы заменить все языки, а в том, чтобы занять сильные ниши: infrastructure, backend, systems, security, embedded, WebAssembly и performance-critical компоненты.

Как изучать Rust

Лучше не начинать с async, unsafe и макросов. Сначала нужно понять базу.

С чего начать:

  • базовый синтаксис (переменные, циклы, функции);

  • structenummatch;

  • модули;

  • Option и Result;

  • ownership, borrowing, lifetimes.

Лучшие ресурсы:

  • «The Rust Programming Language» (официальная книга, «The Book») — бесплатно онлайн, есть русский перевод. Обязательна к прочтению.

  • Rust by Example — учимся на готовых примерах (тоже переведена на русский).

  • Rustlings — маленькие упражнения в терминале, чтобы закрепить материал.

  • The Cargo Book — документация по Cargo.

  • Rustonomicon — для тех, кто хочет глубоко разобраться в unsafe.

  • Tokio Tutorial — асинхронное программирование.

  • «Zero To Production In Rust» — для backend-разработчиков.

  • «Command‑Line Rust» — для тех, кто хочет делать CLI-утилиты.

  • «Programming Rust» (ОʼReilly) — более глубокая книга.

  • «Rust for Rustaceans» — для тех, кто уже знает основы.

Rust лучше изучать через практику. Сначала CLI-проекты, потом backend, WASM, embedded или системные задачи — в зависимости от интереса.

Хорошие первые проекты: 

  1. CLI todo‑list.

  2. Mini grep (поиск строк в файле).

  3. Парсер логов (например, веб-сервера) с агрегацией статистики.

  4. JSON/CSV-парсер.

  5. HTTP API на Axum (CRUD по пользователям).

  6. Telegram/Discord бот.

  7. Многопоточный парсер логов (каждый файл в отдельном потоке, сбор статистики через mpsc).

  8. WebAssembly-модуль, вызываемый из JavaScript.

  9. Небольшой прокси-сервер (HTTP или TCP).

  10. Маленький embedded-проект (если есть интерес к железу, например, мигание светодиодом на STM32 или Raspberry Pi Pico).

Стоит ли учить Rust

Да, если:

  • Вы хотите понимать системное программирование на глубоком уровне: как работают память, указатели, стек, куча.

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

  • Вам интересны безопасность, инфраструктура, блокчейн, embedded, WebAssembly.

  • Хотите прокачать мышление о памяти, типах, владении и конкурентности — эти навыки пригодятся в любом языке.

  • Вы готовы потратить несколько недель на преодоление начальной сложности.

Не обязательно прямо сейчас, если:

  • Вы занимаетесь только простым фронтендом (React/Vue/Svelte) и не планируете использовать WASM или bэкенд.

  • Ваш текущий стек (Java enterprise, .NET, Go) полностью закрывает потребности компании, и у вас нет задачи внедрять низкоуровневые оптимизации.

  • Команда не готова к переходу на Rust.

Rust не заменит JavaScript во frontend. Не заменит Python в data science. Не заменит Java во всем enterprise. Не заменит Go во всех микросервисах. И не обязан.

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

Заключение

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

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

XChat — хороший повод снова поговорить о Rust. Но главный вывод не в том, что “раз Маск выбрал Rust, значит всем нужно срочно переписывать проекты”. Главный вывод в другом: если новая система должна быть быстрой, надежной, безопасной по памяти и готовой к высокой нагрузке, Rust становится очень сильным кандидатом.

Если вы хотите писать код, который одновременно быстр, строг и надежен, Rust точно стоит попробовать. Но кофе действительно понадобится много.