7 причин використовувати Rust для наступного проекту розробки

Ви цікавитесь Rust, як розробник? Ця стаття надасть вам детальну інформацію про можливості цієї популярної мови системного програмування, щоб допомогти вам зробити вибір.

Ми заглибимося в світ Rust, розглянемо його унікальну систему типів, підходи до безпеки пам’яті, а також концепцію володіння. Крім того, ми запропонуємо вам перелік корисних ресурсів, які стануть у нагоді на вашому шляху навчання Rust.

Розпочнемо!

Що ж таке Rust?

Rust – це мова програмування, яка орієнтована на системний рівень. Її історія бере початок у 2006 році, як персональний проект розробника Грейдона Хоара. Менше ніж за 10 років Rust завоював популярність серед розробників системного програмного забезпечення та інших подібних напрямків. Середній дохід розробника Rust становить приблизно 120 000 доларів на рік.

Якщо ви розглядаєте можливість переходу з C++ на Rust або шукаєте нову мову для вивчення, Rust може стати відмінним вибором! За даними опитування StackOverflow, Rust визнається найулюбленішою мовою програмування вже сім років поспіль.

Джерело зображення: StackOverflow

Rust вдало поєднує в собі швидкодію, притаманну низькорівневим мовам, таким як C і C++, з безпекою, яку пропонують високорівневі мови, наприклад, Python.

Rust знаходить широке застосування в різноманітних сферах розробки програмного забезпечення, від відомих проектів, як Dropbox і Firefox, до WebAssembly і вбудованих систем. Для зручності керування пакетами Rust пропонує Cargo.

Cargo: Керування пакетами в Rust

Cargo є менеджером пакетів для Rust. За його допомогою можна легко встановлювати пакети з crates.io – офіційного репозиторію Rust. Cargo не тільки дозволяє знаходити, встановлювати та керувати пакетами, але й використовується для запуску тестів, генерації документації та в якості системи збірки.

Тепер, коли ви маєте загальне уявлення про Rust, давайте детальніше розглянемо деякі особливості, що роблять його популярною мовою системного програмування.

Зрозумілі повідомлення про помилки

У процесі навчання програмуванню неминуче виникають помилки, на усунення яких може знадобитися чимало часу. Повідомлення про помилки та попередження, що надаються компілятором, є вашими надійними помічниками у цій справі. Чим зрозуміліші ці повідомлення, тим швидше ви зможете виправити недоліки у вашому коді.

Приклад повідомлення про помилку

Коли ваш код не проходить компіляцію, Rust надає детальні повідомлення про помилки, в яких пояснюється, що саме потрібно виправити і де саме.

У наведеному прикладі змінна `num2` оголошена всередині функції `inner()`, що обмежує її область видимості. Спроба доступу до цієї змінної за межами функції призведе до помилки компіляції:

fn main() {
    let num1 = 10;
    fn inner(){
        let num2 = 9; 
    }
    println!("Значення num2: {}", num2);
}

Повідомлення про помилку чітко вказує на проблему та пропонує можливі шляхи її вирішення.

error[E0425]: не вдалося знайти значення `num2` в цій області видимості
 --> src/main.rs:6:42
  |
6 |     println!("Значення num2: {}", num2);
  |                                          ^^^^ підказка: існує локальна змінна зі схожим іменем: `num1`

Попередження під час компіляції

Компідятор Rust також виводить корисні попередження про потенційні проблеми у вашому коді. Наприклад, якщо ви оголосите змінну, але не використовуєте її в подальшому, компілятор видасть попереджувальне повідомлення, як показано нижче.

fn main() {
    let num1 = 10;
    let num2 = 9;
    println!("Значення num1: {}", num1);
}

У цьому прикладі змінна `num2` оголошена, але ніде не використовується.

warning: невикористана змінна: `num2`
 --> src/main.rs:3:9
  |
3 |     let num2 = 9;
  |         ^^^^ підказка: якщо це навмисно, додайте префікс підкреслення: `_num2`
  |

Строго типізована мова

Ще одна причина звернути увагу на Rust – це його система типів. Rust є строго типізованою мовою, що означає, що неявне приведення типів не підтримується. Неявне приведення типів – це ситуація, коли мова автоматично перетворює значення одного типу даних на інший.

Наприклад, наступний код Python виконається без помилок. Це пов’язано з тим, що в Python будь-яке число, що не дорівнює нулю, вважається `True`, тому оператор `if` виконується без проблем, навіть якщо 10 – це ціле число, а не логічне.

num1 = 10
if num1:
    num2 = 9
print(f"num2 = {num2}")

# Вивід: num2 = 9

На відміну від цього, Rust не допускає неявного приведення типів. Тому наступний код призведе до помилки компіляції:

fn main() {
    let num1 = 10;
    if num1{
        let num2 = 9; 
    }
}

Повідомлення про помилку вказує на невідповідність типів: очікується логічне значення, а отримано ціле.

error[E0308]: невідповідність типів
 --> src/main.rs:3:8
  |
3 |     if num1{
  |        ^^^^ очікувався `bool`, знайдено ціле

Безпека пам’яті

Безпека пам’яті є ще однією важливою перевагою Rust. Ми спробуємо дати стислий огляд того, як це працює.

Ініціалізація змінних перед використанням

У Rust всі змінні повинні бути ініціалізовані перед використанням. У мовах, таких як C, наступний код, де змінна `num` не ініціалізована, компілюється та виконується без помилок. Значення неініціалізованої змінної є деяким “сміттєвим” значенням.

#include <stdio.h>

int main(void) {
    int num;
	printf("Значення num: %d", num);
	return 0;
}
// Вивід: Значення num: 0

Спроба зробити щось подібне в Rust призведе до помилки компіляції. Rust не має поняття про збирання сміття.

fn main() {
    let num:i32;
    println!("Значення num: {}",num);
}
error[E0381]: використане прив'язування `num` не ініціалізовано
 --> src/main.rs:3:40
  |
2 |     let num:i32;
  |         --- прив'язування оголошено тут, але не ініціалізовано
3 |     println!("Значення num: {}",num);
  |                                        ^^^ `num` використовується тут, але не ініціалізовано
  |

Безпека пам’яті під час компіляції

Rust гарантує безпеку пам’яті на етапі компіляції. Розглянемо простий приклад. Хоча умова `if` завжди виконується (має значення `true`), а отже, `num` завжди має бути 100, ми отримуємо помилку при спробі вивести значення `num`.

fn main() {
    let num:i32;
    if true{
        num = 100;
    }
    println!("Значення num: {}", num);
}

Це відбувається тому, що умовні вирази обчислюються під час виконання, і компілятор не може гарантувати, що `num` матиме певне значення на момент компіляції.

error[E0381]: використане прив'язування `num` можливо не ініціалізовано
 --> src/main.rs:6:41
  |
2 |     let num:i32;
  |         --- прив'язування оголошено тут, але не ініціалізовано
3 |     if true{
  |        ---- якщо ця умова `if` є `false`, `num` не ініціалізується
4 |         num = 100;
5 |     }
  |      - тут може бути відсутня гілка `else`, що ініціалізує `num`
6 |     println!("Значення num: {}", num);
  |                                         ^^^ `num` використовується тут, але можливо не ініціалізовано

Якщо уважно придивитися до повідомлення про помилку, то можна помітити, що, додавши гілку `else`, ми можемо гарантувати, що `num` матиме значення. Таким чином, наступний код виконається без помилок. Тому що тепер компілятор може перевірити, що змінна `num` матиме значення під час компіляції, і не буде помилок.

fn main() {
    let num:i32;
    if true{
        num = 100;
    }
    else{
        num = 50;
    }
    println!("Значення num: {}", num);
}
Значення num: 100

Незмінність змінних

Також важливо відзначити, що змінні в Rust за замовчуванням є незмінними. Це означає, що вам, як розробнику, не потрібно турбуватися про випадкове перезаписування значення змінної. Ось приклад:

fn main() {
    let num1 = 10;
    num1 = 5;
    println!("Значення num1: {}", num1);
}

Оскільки `num1` спочатку ініціалізовано значенням 10, спроба присвоїти йому значення 5 призведе до помилки “неможливо повторно присвоїти значення незмінній змінній `num1`”.

error[E0384]: неможливо присвоїти значення незмінній змінній `num1` двічі
 --> src/main.rs:3:5
  |
2 |     let num1 = 10;
  |         ----
  |         |
  |         перше присвоєння `num1`
  |         підказка: розгляньте можливість зробити прив'язування змінним: `mut num1`
3 |     num1 = 5;
  |     ^^^^^^^^ неможливо присвоїти значення незмінній змінній двічі

Володіння та позичання

Концепція володіння відіграє ключову роль у забезпеченні безпеки пам’яті в Rust. Функціонально, володіння в Rust можна описати так:

Кожен об’єкт має одного і тільки одного власника. Якщо власник виходить за межі області видимості, об’єкт знищується.

Розглянемо простий приклад. Тут ми ініціалізуємо рядок `str1`, а потім переміщуємо його значення в `str2`. Оскільки об’єкт може мати лише одного власника, `str1` стає недійсним після переміщення його значення до `str2`.

fn main() {
    let str1 = String::from("Rust");
    let str2 = str1;
    println!("Значення str1: {}", str1);
}
error[E0382]: позика переміщеного значення: `str1`
 --> src/main.rs:4:42
  |
2 |     let str1 = String::from("Rust");
  |         ---- переміщення відбувається, тому що `str1` має тип `String`, що не реалізує trait `Copy`
3 |     let str2 = str1;
  |                ---- значення переміщено сюди
4 |     println!("Значення str1: {}", str1);
  |                                          ^^^^ значення позичається тут після переміщення

Хоча це може здаватися не зовсім очевидним, для кращого розуміння концепції володіння важливо також вивчити принципи позичання та посилань.

Швидка розробка

Ми вже розглянули декілька важливих можливостей мови Rust. Нагадаємо ще деякі:

  • Rust оптимізований як для швидкості, так і для безпеки.
  • Він має вбудований інструмент керування пакетами та систему збірки.
  • Він також пропонує велику стандартну бібліотеку.

Загалом, Rust пропонує все, що може знадобитися розробнику. Тому з Rust ви можете розробляти програми швидко, з мінімальним налагодженням і швидкими збірками.

Кросплатформеність

З Rust ви можете розробляти програми для різних платформ за вашим вибором. Rust підтримує найпоширеніші операційні системи: Linux, macOS і Windows.

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

Активна спільнота значно полегшує процес вивчення. Rust має велику базу користувачів, яка постійно зростає.

Популярність Rust в опитуванні StackOverflow підтверджує наявність великої спільноти користувачів, де багато досвідчених розробників готові ділитися своїми знаннями та досвідом.

Окрім офіційної документації, існує також сайт документації, створений спільнотою, та форум для обговорення. Ви також можете переглянути відповідні обговорення в групах Rust на Reddit і LinkedIn.

Навчальні ресурси для початку роботи з Rust

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

#1. Rust на прикладах

Rust By Example навчить вас основам Rust та стандартним бібліотекам через серію прикладів, які можна запускати в онлайн-редакторі.

Розглянуті теми включають crates, cargo (інструмент для керування пакетами Rust), генерики, особливості, обробку помилок та багато іншого.

#2. Rustlings

Rustlings – це ще один офіційний навчальний ресурс для мови Rust. Він має схожий підхід на Rust By Example. Проте, вам потрібно буде налаштувати локальне середовище розробки, клонувати репозиторій з прикладами та вирішувати прості завдання, щоб вивчити ці концепції.

#3. Rust трек на Exercism

Rust Track на Exercism містить понад 100 вправ, які допоможуть вам вивчити та закріпити розуміння Rust. Exercism – це безкоштовна платформа, де ви можете отримувати допомогу від досвідчених програмістів, а також кодувати, виконуючи вправи.

#4. Інтенсивний курс Ultimate Rust

Інтенсивний курс Ultimate Rust, який веде Натан Стокс на Udemy, охоплює такі теми:

  • Основи програмування на Rust
  • Модульна система в Rust
  • Типи даних і керування потоком
  • Позичання і посилання
  • Структури, traits та колекції

#5. Ultimate Rust 2: проміжні концепції

Ultimate Rust 2 є продовженням курсу Ultimate Rust Crash Course і охоплює такі теми:

  • Замикання
  • Ітератори
  • Обробка помилок
  • Юніт та інтеграційне тестування
  • Журналювання, багатопотоковість і канали

#6. Rust lang: Повний посібник для початківців 2023

Цей курс на Udemy, викладачем якого є Каталін Стефан, є комплексним курсом програмування на Rust. Деякі з розглянутих тем включають:

  • Основи Rust
  • Типи даних, керуючі структури
  • Функції, traits
  • Керування пам’яттю
  • Паралелізм

#7. Програмування Rust: швидка, безпечна розробка систем

Programming Rust від O’Reilly – популярна книга про програмування на Rust, яка навчить вас наступному:

  • Основні типи даних
  • Володіння та позичання
  • Асинхронне програмування
  • Швидкі багатопотокові програми
  • Замикання, ітератори
  • Колекції

#8. Мова програмування Rust, 2-е видання

Книгу “Мова програмування Rust” написали відомі учасники спільноти Rust. Вона охоплює все, що вам потрібно знати про Rust, включаючи:

  • Володіння та позичання
  • Дженерики, traits
  • Розумні покажчики, багатопотоковість
  • Тестування та налагодження

#9. Повний довідник з програмування на Rust

Повний довідник з програмування Rust від Packt охоплює наступне:

  • Реалізація структур даних у Rust
  • Написання багаторазових і тестованих компонентів у Rust
  • Проєктування багатопотокових програм, проєктування алгоритмів
  • Застосування Rust у програмах WebAssembly, мережі та командного рядка

#10. Креативні проєкти для програмістів Rust

Якщо ви досвідчений розробник, який вивчає Rust, створення кількох проєктів у вашій галузі буде корисним для кращого розуміння мови. Креативні проєкти для програмістів Rust від Packt – це книга, яка навчає Rust, застосовуючи його до таких проєктів, як:

  • Створення веб-сервісів RESTful
  • 2D ігри
  • Розробка веб-додатків за допомогою WebAssembly
  • Емулятори машинної мови
  • та багато іншого!

Висновок

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

Наступним кроком ви можете обрати один або декілька з наведених ресурсів, щоб вивчити основи Rust. Бажаємо вам успішного програмування на Rust!

Також ви можете ознайомитися з найкращими постачальниками хостингу для серверів Rust.