Справочная карточка
Руководство по выбору паттерна
Нужна безопасность типов для примитивов?
└── Паттерн newtype (гл. 3)
Нужно обеспечить состояния на этапе компиляции?
└── Паттерн type-state (гл. 3)
Нужен «тег» без данных во время выполнения?
└── PhantomData (гл. 4)
Нужно разорвать циклы ссылок Rc/Arc?
└── Weak<T> / sync::Weak<T> (гл. 9)
Нужно дождаться условия без активного опроса?
└── Condvar + Mutex (гл. 6)
Нужно обрабатывать «один из N типов»?
├── Известное закрытое множество → перечисление (enum)
├── Открытое множество, горячий путь → обобщения
├── Открытое множество, холодный путь → dyn Trait
└── Полностью неизвестные типы → Any + TypeId (гл. 2)
Нужно разделяемое состояние между потоками?
├── Простой счётчик или флаг → атомарные типы
├── Короткая критическая секция → Mutex
├── Много чтений → RwLock
├── Ленивая однократная инициализация → OnceLock / LazyLock (гл. 6)
└── Сложное состояние → актор + каналы
Нужно распараллелить вычисления?
├── Обработка коллекций → rayon::par_iter
├── Фоновая задача → thread::spawn
└── Заимствование локальных данных → thread::scope
Нужен асинхронный ввод-вывод или конкурентная работа с сетью?
├── Базовый уровень → tokio + async/await (гл. 16)
└── Продвинутый (потоки, middleware) → см. Async Rust Training
Нужна обработка ошибок?
├── Библиотека → thiserror (#[derive(Error)])
└── Приложение → anyhow (Result<T>)
Нужно запретить перемещение значения?
└── Pin<T> (гл. 9): обязателен для Future и самоссылающихся типов
Шпаргалка по границам трейтов
| Ограничение | Значение |
|---|---|
T: Clone | Можно дублировать |
T: Send | Можно передать в другой поток |
T: Sync | &T можно разделять между потоками |
T: 'static | Не содержит заимствованных ссылок с ограниченным временем жизни |
T: Sized | Размер известен на этапе компиляции (по умолчанию) |
T: ?Sized | Размер может быть неизвестен ([T], dyn Trait) |
T: Unpin | Безопасно перемещать после закрепления (pin) |
T: Default | Есть значение по умолчанию |
T: Into<U> | Можно преобразовать в U |
T: AsRef<U> | Можно заимствовать как &U |
T: Deref<Target = U> | Автоматически разыменовывается в &U |
F: Fn(A) -> B | Вызываемый, заимствует состояние неизменяемо |
F: FnMut(A) -> B | Вызываемый, может изменять состояние |
F: FnOnce(A) -> B | Вызываемый ровно один раз, может потребить состояние |
Правила elision времён жизни
Компилятор автоматически вставляет времена жизни в трёх случаях, чтобы вам не приходилось делать это вручную:
#![allow(unused)]
fn main() {
// Правило 1: каждый параметр-ссылка получает собственное время жизни
// fn foo(x: &str, y: &str) → fn foo<'a, 'b>(x: &'a str, y: &'b str)
// Правило 2: если есть ровно ОДНО входное время жизни, оно используется для всех выходных
// fn foo(x: &str) -> &str → fn foo<'a>(x: &'a str) -> &'a str
// Правило 3: если один из параметров это &self или &mut self, используется его время жизни
// fn foo(&self, x: &str) -> &str → fn foo<'a>(&'a self, x: &str) -> &'a str
}
Когда время жизни НУЖНО писать явно:
- Несколько входных ссылок и ссылка на выходе (компилятор не может угадать, какой вход имеется в виду)
- Поля структур, которые хранят ссылки:
struct Ref<'a> { data: &'a str } - Границы
'static, когда нужны данные без заимствованных ссылок
Распространённые производные трейты
#![allow(unused)]
fn main() {
#[derive(
Debug, // Форматирование {:?}
Clone, // .clone()
Copy, // Неявное копирование (только для простых типов)
PartialEq, Eq, // Сравнение ==
PartialOrd, Ord, // Сравнение < > и сортировка
Hash, // Ключ HashMap/HashSet
Default, // Type::default()
)]
struct MyType { /* ... */ }
}
Краткая справка по видимости модулей
pub → видим везде
pub(crate) → видим внутри крейта
pub(super) → видим родительскому модулю
pub(in path) → видим внутри конкретного пути
(ничего) → приватен для текущего модуля и его потомков
Дополнительная литература
| Ресурс | Почему стоит прочитать |
|---|---|
| Rust Design Patterns | Каталог идиоматичных паттернов и антипаттернов |
| Rust API Guidelines | Официальный чек-лист для аккуратных публичных API |
| Rust Atomics and Locks | Глубокий разбор примитивов конкурентности от Mara Bos |
| The Rustonomicon | Официальное руководство по unsafe Rust и тёмным углам языка |
| Error Handling in Rust | Подробное руководство Andrew Gallant |
| Jon Gjengset — Crust of Rust series | Глубокие разборы итераторов, времён жизни, каналов и др. |
| Effective Rust | 35 конкретных способов улучшить ваш код на Rust |
Конец книги «Паттерны Rust и практические руководства по инженерии»