Skip to content

Instantly share code, notes, and snippets.

@rdnvndr
Created April 16, 2026 04:54
Show Gist options
  • Select an option

  • Save rdnvndr/ec86d649b951ce739e8f6d49feff7897 to your computer and use it in GitHub Desktop.

Select an option

Save rdnvndr/ec86d649b951ce739e8f6d49feff7897 to your computer and use it in GitHub Desktop.
RUST MEMENTO
================================================================================
RUST MEMENTO
================================================================================
1. ПЕРЕМЕННЫЕ, ТИПЫ, ВЫВОД
================================================================================
let x = 5; // неизменяемая (по умолчанию)
let mut y = 10; // изменяемая
let z: i32 = 42; // с явным типом
let _ignored = 99; // подчёркивание — не использовать, но не warning
// Теневые переменные (shadowing)
let w = 1;
let w = w + 5; // новая переменная w, старая недоступна
let w = String::from("теперь строка"); // тип тоже может измениться
// Константы (всегда неизменяемы, тип обязателен, можно вычислять)
const SECONDS_IN_HOUR: u32 = 3600;
const ARRAY_SIZE: usize = 10;
// Статические переменные (глобальные)
static GLOBAL: i32 = 42;
static mut MUT_GLOBAL: i32 = 100; // unsafe для чтения/записи
// Вывод в консоль (макросы)
print!("без перевода строки");
println!("с переводом строки");
println!("{} + {} = {}", 2, 3, 5);
println!("{1} + {0} = {2}", 2, 3, 5); // по индексам
println!("{a} + {b} = {c}", a=2, b=3, c=5);
println!("{:?}", (1, "hello", true)); // Debug (для отладки)
println!("{:#?}", large_struct); // красивое форматирование
println!("{:b} {:x} {:o}", 255, 255, 255); // двоичн, шестн, восьм
// Макрос для отладки (выводит файл, строку, значение)
dbg!(&x);
dbg!(y * 2);
2. ЦЕЛОЧИСЛЕННЫЕ ТИПЫ (размеры и диапазоны)
================================================================================
// Знаковые (signed)
i8: -128 .. 127
i16: -32768 .. 32767
i32: -2_147_483_648 .. 2_147_483_647
i64: -9_223_372_036_854_775_808 .. 9_223_372_036_854_775_807
i128: огромный
isize: зависит от архитектуры (32/64 бита) — для индексов в коллекциях
// Беззнаковые (unsigned)
u8: 0 .. 255
u16: 0 .. 65535
u32: 0 .. 4_294_967_295
u64: 0 .. 18_446_744_073_709_551_615
u128: огромный
usize: зависит от архитектуры — для размеров и индексов
// Литералы
let a = 0xFF; // шестнадцатеричные
let b = 0o77; // восьмеричные
let c = 0b1111; // двоичные
let d = 1_000_000; // визуальный разделитель
let e = b'A'; // байтовый литерал (u8)
// Методы для чисел
let x = -42;
println!("{}", x.abs());
let y = 5u8;
println!("{}", y.checked_add(250)); // Some(255) или None
println!("{}", y.saturating_add(250)); // 255 (насыщение)
println!("{}", 10_i32.pow(3)); // 1000
3. ВЕЩЕСТВЕННЫЕ ТИПЫ
================================================================================
f32: 32-битное, одинарная точность
f64: 64-битное, двойная точность (по умолчанию)
let pi: f64 = 3.1415926535;
let exp = 2.5e-3; // 0.0025
let inf = f64::INFINITY;
let nan = f64::NAN;
// Проверки
println!("{}", pi.is_nan());
println!("{}", pi.is_infinite());
println!("{}", pi.is_finite());
// Методы
let a = 3.0;
let b = 4.0;
println!("{}", a.sqrt());
println!("{}", a.powi(2)); // целая степень
println!("{}", a.powf(0.5)); // вещественная степень
println!("{}", a.hypot(b)); // sqrt(a² + b²)
4. ЛОГИЧЕСКИЙ ТИП И СИМВОЛЫ
================================================================================
let t = true;
let f: bool = false;
// Символы (Unicode, 4 байта)
let c = 'я';
let omega = 'Ω';
let smile = '😊';
let code = '\u{1F600}'; // Unicode escape
// Методы символов
println!("{}", c.is_alphabetic());
println!("{}", c.is_numeric());
println!("{}", c.to_ascii_uppercase());
5. КОРТЕЖИ (TUPLES)
================================================================================
let tup: (i32, f64, char) = (42, 3.14, 'R');
let (a, b, c) = tup; // деструктуризация
let first = tup.0; // доступ по индексу
let second = tup.1;
// Кортеж из одного элемента (нужна запятая)
let singleton = (5,);
// Пустой кортеж (unit)
let unit = (); // тип () — используется как "ничего", например в Result<(), Error>
6. МАССИВЫ (ARRAYS) — фиксированная длина
================================================================================
let arr1 = [1, 2, 3, 4, 5];
let arr2: [i32; 5] = [1, 2, 3, 4, 5];
let zeros = [0; 100]; // 100 нулей
let first = arr1[0]; // доступ (паника при выходе за границы)
let maybe = arr1.get(10); // Option<&i32> — безопасный доступ
// Итерация
for elem in &arr1 {
println!("{}", elem);
}
for elem in arr1.iter() { ... }
for (i, elem) in arr1.iter().enumerate() { ... }
7. СРЕЗЫ (SLICES) — ссылка на часть коллекции
================================================================================
let arr = [10, 20, 30, 40, 50];
let slice1: &[i32] = &arr[1..4]; // [20, 30, 40]
let slice2 = &arr[..3]; // [10, 20, 30]
let slice3 = &arr[2..]; // [30, 40, 50]
let slice4 = &arr[..]; // весь массив как срез
// Срезы строк (самый частый случай)
let s = String::from("hello world");
let hello = &s[0..5]; // &str
let world = &s[6..11];
// ВНИМАНИЕ: срезы по байтам, не по символам!
// &s[0..1] на "привет" — паника, т.к. символы UTF-8 многобайтные
8. СТРОКИ (ДВЕ СУЩНОСТИ)
================================================================================
// 1. &str — строковый срез (неизменяемый, часть String или литерал)
let literal: &str = "Hello";
let part: &str = &some_string[0..5];
// 2. String — изменяемая строка в куче
let mut s = String::new();
let s2 = String::from("hello");
let s3 = "world".to_string();
let s4 = "rust".to_owned();
// Методы String
let mut s = String::from("hello");
s.push_str(" world"); // добавление &str
s.push('!'); // добавление символа
s += "!!!"; // оператор (требует &str)
s.insert(5, ','); // вставка символа на позицию
s.remove(5); // удаление символа
s.pop(); // удаление последнего символа
let len = s.len(); // длина в байтах
let is_empty = s.is_empty();
// Конкатенация (format! — без перемещения владения)
let a = "Hello";
let b = "World";
let c = format!("{} {}!", a, b); // a и b остаются доступны
// Преобразования
let num = 42;
let num_str = num.to_string();
let parsed: i32 = "42".parse().unwrap();
let parsed2 = "42".parse::<i32>().unwrap();
// Итерация по символам (а не байтам!)
for ch in "привет".chars() {
println!("{}", ch);
}
for byte in "hello".bytes() {
println!("{}", byte);
}
9. ВЛАДЕНИЕ (OWNERSHIP) — подробно
================================================================================
ПРАВИЛА:
1. Каждое значение имеет одну переменную — владельца.
2. Владелец может быть только один.
3. Когда владелец выходит из области видимости, значение удаляется (drop).
// Перемещение (move)
let s1 = String::from("hello");
let s2 = s1; // s1 перемещён в s2, s1 больше не действителен
// println!("{}", s1); // ОШИБКА!
// Копирование (copy) — только для типов, реализующих Copy (стековые)
let x = 5;
let y = x; // x копируется, оба действительны
// Копируемые типы: все целые, bool, char, f32/f64, кортежи из копируемых
// Клонирование (clone) — явное глубокое копирование
let s1 = String::from("hello");
let s2 = s1.clone(); // оба действительны, но дорого
// Функции и владение
fn take(s: String) { ... } // забирает владение, s уничтожится после вызова
fn make() -> String { ... } // возвращает владение
let s = String::from("hello");
take(s); // s больше не действителен
// println!("{}", s); // ОШИБКА!
10. ЗАИМСТВОВАНИЕ (BORROWING)
================================================================================
// Неизменяемое заимствование (&T) — можно сколько угодно
fn calc_len(s: &String) -> usize { // берёт &String, не забирает владение
s.len()
}
let s = String::from("hello");
let len = calc_len(&s); // передаём ссылку
println!("{} {}", s, len); // s всё ещё действителен
// Изменяемое заимствование (&mut T) — можно только одно
fn modify(s: &mut String) {
s.push_str(" world");
}
let mut s = String::from("hello");
modify(&mut s); // передаём изменяемую ссылку
// ПРАВИЛА БОРРОУИНГА:
// - Нельзя иметь изменяемую ссылку, если есть неизменяемые
// - Нельзя иметь изменяемую ссылку и использовать оригинал
let mut s = String::from("hello");
let r1 = &s; // OK
let r2 = &s; // OK
// let r3 = &mut s; // ОШИБКА! нельзя, т.к. есть неизменяемые
println!("{} {}", r1, r2);
let mut s = String::from("hello");
let r1 = &mut s; // OK
// let r2 = &s; // ОШИБКА! нельзя неизменяемую, когда есть изменяемая
// println!("{}", s); // ОШИБКА! нельзя использовать оригинал
// Ссылки не могут жить дольше, чем данные, на которые указывают
11. ВРЕМЯ ЖИЗНИ (LIFETIMES)
================================================================================
// АННОТАЦИИ: 'a, 'b, 'static и т.д.
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() { x } else { y }
}
// Структуры со ссылками
struct Excerpt<'a> {
part: &'a str,
}
let novel = String::from("Call me Ishmael...");
let first_sentence = novel.split('.').next().expect("no .");
let excerpt = Excerpt { part: first_sentence };
// 'static — живёт всю программу (строковые литералы)
let s: &'static str = "I live forever";
// Элизия (elision) — правила, когда аннотации можно опускать
fn first_word(s: &str) -> &str { // компилятор сам добавит 'a
&s[..1]
}
12. ВЕКТОРЫ (VEC<T>)
================================================================================
let mut v: Vec<i32> = Vec::new();
let v2 = vec![1, 2, 3]; // макрос vec!
// Добавление и удаление
v.push(5);
v.push(6);
v.pop(); // Option<T>
v.insert(1, 10); // на позицию 1 вставить 10
v.remove(0); // удалить индекс 0
// Доступ
let third = &v[2]; // паника при выходе
let third_opt = v.get(2); // Option<&i32>
let mut_third = &mut v[2];
// Итерация
for i in &v { println!("{}", i); }
for i in &mut v { *i += 10; } // изменение через разыменование
for i in v.iter().enumerate() { ... }
// Ёмкость (capacity) и размер (len)
let mut v = Vec::with_capacity(100); // заранее выделить память
v.push(1);
println!("len: {}, cap: {}", v.len(), v.capacity());
v.shrink_to_fit(); // уменьшить capacity до len
// Преобразование из итератора
let v: Vec<i32> = (1..10).collect();
13. ХЭШ-ТАБЛИЦЫ (HASHMAP)
================================================================================
use std::collections::HashMap;
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
// entry + or_insert (идиоматично)
scores.entry(String::from("Blue")).or_insert(25); // не изменит, т.к. есть
scores.entry(String::from("Red")).or_insert(30); // вставит
// Обновление значения
let text = "hello world wonderful world";
let mut map = HashMap::new();
for word in text.split_whitespace() {
let count = map.entry(word).or_insert(0);
*count += 1;
}
// Итерация
for (key, value) in &scores {
println!("{}: {}", key, value);
}
// Владение
let key = String::from("Blue");
scores.insert(key, 10); // key перемещён в map, использовать нельзя
// Альтернативы: BTreeMap (отсортированный)
14. ПЕРЕЧИСЛЕНИЯ (ENUM) — мощь Rust
================================================================================
enum IpAddr {
V4(u8, u8, u8, u8),
V6(String),
}
let home = IpAddr::V4(127, 0, 0, 1);
let loopback = IpAddr::V6(String::from("::1"));
impl IpAddr {
fn call(&self) { ... }
}
// Option<T> — встроенный (не нужно Null)
enum Option<T> {
Some(T),
None,
}
let some_num = Some(5);
let some_str = Some("text");
let absent: Option<i32> = None;
// Result<T, E> — обработка ошибок
enum Result<T, E> {
Ok(T),
Err(E),
}
let f = File::open("hello.txt"); // Result<File, std::io::Error>
15. MATCH — исчерпывающее сопоставление
================================================================================
let value = 3;
match value {
1 => println!("один"),
2 | 3 | 5 | 7 => println!("простое число"),
4..=10 => println!("от 4 до 10"),
_ => println!("что-то ещё"),
}
// match с Option
fn plus_one(x: Option<i32>) -> Option<i32> {
match x {
None => None,
Some(i) => Some(i + 1),
}
}
// match с Result
match File::open("file.txt") {
Ok(file) => println!("открыто: {:?}", file),
Err(e) => println!("ошибка: {}", e),
}
// if let — когда нужна только одна ветка
let config_max = Some(3u8);
if let Some(max) = config_max {
println!("максимум {}", max);
}
// с else
if let Some(max) = config_max {
println!("{}", max);
} else {
println!("нет значения");
}
// while let
let mut stack = Vec::new();
stack.push(1);
stack.push(2);
while let Some(top) = stack.pop() {
println!("{}", top);
}
16. СТРУКТУРЫ (STRUCT) — методы и ассоциированные функции
================================================================================
struct Rectangle {
width: u32,
height: u32,
}
// Методы (первый параметр self, &self, &mut self)
impl Rectangle {
fn area(&self) -> u32 {
self.width * self.height
}
fn can_hold(&self, other: &Rectangle) -> bool {
self.width > other.width && self.height > other.height
}
fn set_width(&mut self, w: u32) {
self.width = w;
}
// Ассоциированная функция (конструктор, без self)
fn square(size: u32) -> Self {
Self { width: size, height: size }
}
}
let rect = Rectangle { width: 30, height: 50 };
println!("{}", rect.area());
let square = Rectangle::square(20);
// Кортежные структуры
struct Color(u8, u8, u8);
let black = Color(0, 0, 0);
println!("{}", black.0);
// Unit-структура (для реализации trait, без данных)
struct Marker;
17. ОБОБЩЕНИЯ (GENERICS)
================================================================================
struct Point<T> {
x: T,
y: T,
}
let int_point = Point { x: 5, y: 10 };
let float_point = Point { x: 1.0, y: 4.0 };
struct Mixed<T, U> {
x: T,
y: U,
}
impl<T> Point<T> {
fn x(&self) -> &T { &self.x }
}
impl Point<f64> { // только для f64
fn distance_from_origin(&self) -> f64 {
(self.x.powi(2) + self.y.powi(2)).sqrt()
}
}
// В функциях
fn largest<T: PartialOrd>(list: &[T]) -> &T {
let mut largest = &list[0];
for item in list {
if item > largest { largest = item; }
}
largest
}
18. TRAIT'Ы — интерфейсы
================================================================================
trait Summary {
fn summarize(&self) -> String;
fn default_impl(&self) -> String { // реализация по умолчанию
String::from("(default)")
}
}
struct NewsArticle {
headline: String,
location: String,
}
impl Summary for NewsArticle {
fn summarize(&self) -> String {
format!("{}, by {}", self.headline, self.location)
}
}
// Trait как параметр (синтаксис)
fn notify(item: &impl Summary) { ... }
fn notify2<T: Summary>(item: &T) { ... } // то же самое
fn notify3<T: Summary + Display>(item: &T) { ... } // несколько
fn notify4<T>(item: &T) where T: Summary + Display { ... } // где-клауза
// Возврат типа, реализующего trait
fn returns_summarizable() -> impl Summary {
NewsArticle { ... }
}
// Ограничение: можно вернуть только один конкретный тип
// Реализация внешнего trait для внешнего типа (сиротское правило)
// Нужно хотя бы одно из них локальное
19. ОБРАБОТКА ОШИБОК (паника и Result)
================================================================================
// Паника (неустранимая)
panic!("crash and burn");
let v = vec![1, 2, 3];
v[99]; // паника
// Result (устранимая)
use std::fs::File;
use std::io::ErrorKind;
let f = File::open("hello.txt");
let f = match f {
Ok(file) => file,
Err(error) => match error.kind() {
ErrorKind::NotFound => match File::create("hello.txt") {
Ok(fc) => fc,
Err(e) => panic!("не могу создать: {:?}", e),
},
other_error => panic!("другая ошибка: {:?}", other_error),
},
};
// unwrap и expect (паника при Err)
let f = File::open("hello.txt").unwrap();
let f = File::open("hello.txt").expect("не удалось открыть hello.txt");
// Оператор ? — распространение ошибки
use std::io;
use std::io::Read;
fn read_username() -> Result<String, io::Error> {
let mut f = File::open("username.txt")?; // если Err, вернёт его из функции
let mut s = String::new();
f.read_to_string(&mut s)?;
Ok(s)
}
// Короткая версия
fn read_username2() -> Result<String, io::Error> {
let mut s = String::new();
File::open("username.txt")?.read_to_string(&mut s)?;
Ok(s)
}
// Ещё короче (стандартная библиотека)
fn read_username3() -> Result<String, io::Error> {
fs::read_to_string("username.txt")
}
// ? работает с Option тоже
fn last_char_of_first_line(text: &str) -> Option<char> {
text.lines().next()?.chars().last()
}
20. МАКРОСЫ (МАКРОСЫ ПОТОКОВ ТОКЕНОВ)
================================================================================
// Макрос без аргументов
macro_rules! hello {
() => {
println!("Hello!");
};
}
// С аргументами
macro_rules! say {
($name:expr) => {
println!("Hello, {}!", $name);
};
(hello) => {
println!("Hello special!");
};
}
// Повторения
macro_rules! vec_of_strings {
($($x:expr),*) => {
vec![$($x.to_string()),*]
};
}
let v = vec_of_strings!("a", "b", "c");
// Макрос с разными паттернами
macro_rules! calculate {
(eval $e:expr) => {{
let val: usize = $e;
println!("{} = {}", stringify!($e), val);
}};
}
calculate!(eval 2 + 3 * 5);
21. ЗАКРЫТИЯ (CLOSURES)
================================================================================
let add_one = |x: i32| -> i32 { x + 1 };
let add_one_short = |x| x + 1;
let add = |a, b| a + b;
// Захват окружения
let x = 4;
let equal_to_x = |z| z == x; // захват x (не владея, если только move)
let y = 4;
assert!(equal_to_x(y));
// move — передача владения в замыкание
let x = vec![1, 2, 3];
let equal_to_x = move |z| z == x;
// println!("{:?}", x); // ОШИБКА! x перемещён в замыкание
// Применение: итераторы
let v = vec![1, 2, 3];
let doubled: Vec<_> = v.iter().map(|x| x * 2).collect();
22. ИТЕРАТОРЫ
================================================================================
let v = vec![1, 2, 3, 4, 5];
// Ленивые итераторы
let iter = v.iter(); // &T
let iter_mut = v.iter_mut(); // &mut T
let into_iter = v.into_iter(); // T (потребляет коллекцию)
// Адаптеры
let doubled: Vec<_> = v.iter().map(|x| x * 2).collect();
let evens: Vec<_> = v.iter().filter(|x| *x % 2 == 0).collect();
let first_even = v.iter().find(|x| *x % 2 == 0);
let any_greater = v.iter().any(|x| *x > 10);
let all_positive = v.iter().all(|x| *x > 0);
let sum: i32 = v.iter().sum();
let product: i32 = v.iter().product();
// fold (аккумулятор)
let sum = v.iter().fold(0, |acc, x| acc + x);
// zip
let v1 = vec![1, 2];
let v2 = vec![3, 4];
let zipped: Vec<_> = v1.iter().zip(v2.iter()).map(|(a, b)| a + b).collect();
// chain
let concatenated: Vec<_> = v1.iter().chain(v2.iter()).collect();
23. УМНЫЕ УКАЗАТЕЛИ
================================================================================
// Box<T> — указатель на кучу
let b = Box::new(5);
// Рекурсивные типы
enum List {
Cons(i32, Box<List>),
Nil,
}
use List::{Cons, Nil};
let list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));
// Rc<T> — подсчёт ссылок (один поток)
use std::rc::Rc;
let a = Rc::new(List::Cons(5, Rc::new(List::Nil)));
let b = List::Cons(3, Rc::clone(&a));
let c = List::Cons(4, Rc::clone(&a));
println!("count = {}", Rc::strong_count(&a));
// RefCell<T> — внутренняя изменяемость (проверки в runtime)
use std::cell::RefCell;
let x = RefCell::new(5);
*x.borrow_mut() = 6; // изменяем через неизменяемую переменную
let y = x.borrow(); // неизменяемое заимствование
// Комбинация Rc<RefCell<T>> — множественное владение с изменяемостью
let shared = Rc::new(RefCell::new(5));
let a = Rc::clone(&shared);
let b = Rc::clone(&shared);
*a.borrow_mut() = 10;
// Arc<T> — атомарный Rc (для потоков)
use std::sync::Arc;
let shared = Arc::new(42);
// Mutex<T> — взаимное исключение
use std::sync::Mutex;
let m = Mutex::new(5);
{
let mut num = m.lock().unwrap();
*num = 6;
}
24. ПОТОКИ (THREADS)
================================================================================
use std::thread;
use std::time::Duration;
// Запуск потока
let handle = thread::spawn(|| {
for i in 1..10 {
println!("поток: {}", i);
thread::sleep(Duration::from_millis(1));
}
});
for i in 1..5 {
println!("главный: {}", i);
thread::sleep(Duration::from_millis(1));
}
handle.join().unwrap(); // дождаться завершения
// move для захвата владения
let v = vec![1, 2, 3];
let handle = thread::spawn(move || {
println!("{:?}", v);
});
handle.join().unwrap();
// Передача данных между потоками (каналы mpsc)
use std::sync::mpsc;
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
tx.send(42).unwrap();
});
let received = rx.recv().unwrap(); // блокируется
println!("получено: {}", received);
// Несколько продюсеров
let (tx, rx) = mpsc::channel();
let tx1 = tx.clone();
thread::spawn(move || { tx1.send(1).unwrap(); });
thread::spawn(move || { tx.send(2).unwrap(); });
for received in rx { println!("{}", received); }
25. МОДУЛИ И ПРОСТРАНСТВА ИМЁН
================================================================================
// Файл src/lib.rs или src/main.rs
mod front_of_house {
pub mod hosting {
pub fn add_to_waitlist() {}
fn seat_at_table() {}
}
mod serving {
fn take_order() {}
}
}
use crate::front_of_house::hosting;
// или
use front_of_house::hosting::add_to_waitlist;
pub fn eat_at_restaurant() {
hosting::add_to_waitlist();
}
// re-export
pub use self::front_of_house::hosting;
// вложенные пути
use std::{cmp::Ordering, io};
// алиасы
use std::fmt::Result as FmtResult;
// прелюдия (std::prelude) — автоматически импортируется
// Структура проекта
/*
my_project/
Cargo.toml
src/
main.rs (точка входа для бинарного крейта)
lib.rs (точка входа для библиотечного крейта)
front_of_house.rs
back_of_house.rs
*/
26. ТЕСТИРОВАНИЕ
================================================================================
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
#[test]
fn failing() {
panic!("этот тест упадёт");
}
#[test]
fn with_result() -> Result<(), String> {
if 2 + 2 == 4 { Ok(()) } else { Err(String::from("не 4")) }
}
#[test]
#[should_panic(expected = "разделение на ноль")]
fn divide_by_zero() {
panic!("разделение на ноль"); // пройдёт
}
#[test]
#[ignore]
fn expensive_test() { ... }
}
// Интеграционные тесты (в tests/ папке)
// tests/integration_test.rs
use my_crate;
#[test]
fn it_adds() { ... }
// Документационные тесты (внутри /// комментариев)
/// Добавляет два числа.
/// ```
/// assert_eq!(my_crate::add(2, 2), 4);
/// ```
pub fn add(a: i32, b: i32) -> i32 { a + b }
27. КОМАНДЫ CARGO (ПОВСЕДНЕВНЫЕ)
================================================================================
cargo new app # новый бинарный проект
cargo new --lib lib # новый библиотечный проект
cargo build # отладочная сборка (target/debug/)
cargo build --release # релизная сборка (target/release/)
cargo run # сборка + запуск
cargo check # быстрая проверка без генерации кода
cargo test # запуск всех тестов
cargo test -- --nocapture # с выводом println! в тестах
cargo doc --open # документация проекта
cargo update # обновление зависимостей
cargo add serde # добавить зависимость (требуется cargo-edit)
cargo fmt # форматирование кода (rustfmt)
cargo clippy # линтер (много полезных советов)
28. ПОЛЕЗНЫЕ КОМБИНАЦИИ И ПАТТЕРНЫ
================================================================================
// Игнорирование значений в match
let x = Some(5);
match x {
Some(_) => println!("есть значение"),
None => (),
}
// .. для пропуска остальных полей
struct Point { x: i32, y: i32, z: i32 }
let p = Point { x: 1, y: 2, z: 3 };
match p {
Point { x, .. } => println!("x = {}", x),
}
// Рефутинг (ref и ref mut)
let x = Some(5);
match x {
Some(ref r) => println!("ссылка на {}", r), // r: &i32
None => (),
}
// Guard в match
match x {
Some(v) if v < 5 => println!("меньше 5"),
Some(v) => println!("{}", v),
None => (),
}
// @-привязка
match x {
Some(v @ 1..=5) => println!("от 1 до 5: {}", v),
_ => (),
}
================================================================================
ССЫЛКИ И РЕСУРСЫ
================================================================================
- Официальная книга: https://doc.rust-lang.org/book/
- Rust by Example: https://doc.rust-lang.org/rust-by-example/
- Std docs: https://doc.rust-lang.org/std/
- Crates.io: https://crates.io/
- Rust Playground: https://play.rust-lang.org/
================================================================================
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment