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

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

Что такое Rust?

Rust – это язык системного программирования. Он возник как личный проект разработчика Грейдона Хоара в 2006 году. Менее чем за десять лет он превратился в лучший выбор для системного программирования и смежных приложений. Средняя зарплата программиста на Rust составляет около 120 тысяч долларов. Так что если вы хотите перейти с C++ на Rust или хотите освоить новый язык, изучение Rust может стать отличным выбором! Согласно опросу разработчиков StackOverflow, Rust признан самым любимым языком программирования – уже семь лет подряд.

image-96

Rust предлагает скорость низкоуровневых языков системного программирования, таких как C и C++, и безопасность высокоуровневых языков программирования, таких как Python. Rust широко используется во всех областях разработки программного обеспечения- от таких известных проектов, как Dropbox и Firefox, до WebAssembly и встраиваемого программирования. Rust предлагает встроенную поддержку управления пакетами через Cargo.

Cargo: менеджер пакетов для Rust

Cargo – это менеджер пакетов для Rust. Вы можете использовать cargo для установки пакетов из crates, реестра пакетов Rust. Помимо менеджера пакетов, позволяющего искать, устанавливать и управлять пакетами, cargo также служит в качестве прогонщика тестов, генератора документации и системы сборки. Теперь, когда вы получили общее представление о Rust, давайте подробнее рассмотрим некоторые его особенности, которые выделяют его как язык системного программирования, получивший широкое распространение.

Полезные сообщения об ошибках

Helpful-Error-Messages

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

Пример сообщения об ошибке

Когда ваш код не компилируется успешно, Rust выдает полезные сообщения об ошибках, в которых объясняется, что и где нужно исправить в вашем коде. В этом примере переменная num2 определена внутри функции inner(). Поэтому она ограничена областью видимости функции. Если вы попытаетесь получить к ней доступ вне функции, компилятор выдаст ошибку:

fn main() {
    let num1 = 10;
    fn inner(){
        let num2 = 9; 
    }
    println!("The value of num2 is: {}", num2);
}

А сообщение об ошибке дает информацию о том, что нужно исправить.

error[E0425]: cannot find value `num2` in this scope
 --> src/main.rs:6:42
  |
6 |     println!("The value of num2 is: {}", num2);
  |                                          ^^^^ help: a local variable with a similar name exists: `num1`

Предупреждения во время компиляции

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

fn main() {
    let num1 = 10;
    let num2 = 9;
    println!("The value of num1 is: {}", num1);
}

Здесь переменная num2 объявлена, но никогда не используется.

warning: unused variable: `num2`
 --> src/main.rs:3:9
  |
3 |     let num2 = 9;
  |         ^^^^ help: if this is intentional, prefix it with an underscore: `_num2`
  |

Сильно типизированный язык

Еще одна причина, по которой вам стоит использовать Rust в своих проектах, – это его система типов. Rust – сильно типизированный язык, что означает, что он не поддерживает согласование типов. Принуждение типов – это когда язык может неявно преобразовать значение одного типа данных в другой. Например, код Python в следующей ячейке кода будет выполняться без ошибок. Это происходит потому, что в Python ненулевое число имеет истинностное значение True, и поэтому оператор if выполняется без ошибок, несмотря на то, что число 10 является целым числом, а не булевым.

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

# Output: num2 is 9

С другой стороны, Rust не коэрцитирует типы. Поэтому следующий код приведет к ошибке:

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

Ошибка сообщает о несоответствии типов, где ожидалось булево, а оказалось целое число.

error[E0308]: mismatched types
 --> src/main.rs:3:8
  |
3 |     if num1{
  |        ^^^^ expected `bool`, found integer

Копировать

Безопасность памяти

Безопасность памяти – еще одна особенность Rust, которая делает его привлекательным для программистов. Мы постараемся дать беглый обзор того, как это работает.

Переменные должны быть инициализированы до их использования

В Rust все переменные должны быть инициализированы, прежде чем их можно будет использовать. В таких языках, как C, следующий код, в котором num не инициализирована, скомпилируется и выполнится без ошибок. Значением неинициализированной переменной будет какое-то мусорное значение.

#include <stdio.h>

int main(void) {
    int num;
	printf("The value of num is %d", num);
	return 0;
}
// Output: The value of num is 0

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

fn main() {
    let num:i32;
    println!("The value of num is: {}",num);
}
error[E0381]: used binding `num` isn't initialized
 --> src/main.rs:3:40
  |
2 |     let num:i32;
  |         --- binding declared here but left uninitialized
3 |     println!("The value of num is: {}",num);
  |                                        ^^^ `num` used here but it isn't initialized
  |

Безопасность памяти на этапе компиляции

Rust обеспечивает безопасность памяти во время компиляции. Давайте рассмотрим простой пример. Здесь, несмотря на то что условный оператор if имеет булево значение true, что означает, что значение num всегда будет равно 100, мы получаем ошибку при попытке вывести значение num.

fn main() {
    let num:i32;
    if true{
        num = 100;
    }
    println!("The value of num is: {}", num);
}

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

error[E0381]: used binding `num` is possibly-uninitialized
 --> src/main.rs:6:41
  |
2 |     let num:i32;
  |         --- binding declared here but left uninitialized
3 |     if true{
  |        ---- if this `if` condition is `false`, `num` is not initialized
4 |         num = 100;
5 |     }
  |      - an `else` arm might be missing here, initializing `num`
6 |     println!("The value of num is: {}", num);
  |                                         ^^^ `num` used here but it is possibly-uninitialized

Если вы внимательно посмотрите на сообщение об ошибке, то увидите, что с помощью оператора else мы можем гарантировать, что num будет иметь значение. Поэтому следующий код будет выполняться без ошибок. Потому что таким образом компилятор может определить, что num будет иметь значение – во время компиляции – поэтому ошибок не будет.

fn main() {
    let num:i32;
    if true{
        num = 100;
    }
    else{
        num = 50;
    }
    println!("The value of num is: {}", num);
}
The value of num is: 100

Неизменность переменных

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

fn main() {
    let num1 = 10;
    num1 = 5;
    println!("The value of num1 is: {}", num1);
}

Поскольку num1 инициализирована значением 10, при попытке присвоить ей значение 5 вы получите сообщение об ошибке “cannot assign twice to immutable variable num1“.

error[E0384]: cannot assign twice to immutable variable `num1`
 --> src/main.rs:3:5
  |
2 |     let num1 = 10;
  |         ----
  |         |
  |         first assignment to `num1`
  |         help: consider making this binding mutable: `mut num1`
3 |     num1 = 5;
  |     ^^^^^^^^ cannot assign twice to immutable variable

Владение и заимствование

Владение обеспечивает безопасность памяти. Функционально владение в Rust можно описать следующим образом:

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

Давайте рассмотрим простой пример. Здесь мы инициализируем строку str1, а затем перемещаем ее значение в str2. Поскольку у любого объекта может быть только один владелец, объект str1 будет уничтожен, как только его значение переместится в str2.

fn main() {
    let str1 = String::from("Rust");
    let str2 = str1;
    println!("The value of str1 is: {}", str1);
}
error[E0382]: borrow of moved value: `str1`
 --> src/main.rs:4:42
  |
2 |     let str1 = String::from("Rust");
  |         ---- move occurs because `str1` has type `String`, which does not implement the `Copy` trait
3 |     let str2 = str1;
  |                ---- value moved here
4 |     println!("The value of str1 is: {}", str1);
  |                                          ^^^^ value borrowed here after move

Хотя это кажется интуитивно понятным, чтобы лучше понять и оценить, как работает право собственности, полезно ознакомиться с понятиями заимствования и ссылки.

Быстрое развитие

До сих пор мы обсуждали несколько полезных возможностей языка программирования Rust. Рассмотрим некоторые из них:

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

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

Кросс-платформенная разработка

Quick-Development

С помощью Rust вы можете разрабатывать на любой платформе по своему усмотрению. Rust поддерживает самые распространенные платформы: Linux, MacOS и Windows. Разработка приложений в целом проста, поскольку вы можете скомпилировать исходный код Rust в исполняемый файл, не прибегая к помощи других инструментов сборки и внешних компиляторов.

Поддерживающее сообщество

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

Учебные ресурсы для начала работы с Rust

Learning-Resources-to-Get-Started-With-Rust

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

Rust By Example

Rust By Example научит вас основам Rust и стандартным библиотекам с помощью серии примеров, которые вы сможете написать в онлайн-редакторе. Будут рассмотрены такие темы, как crates, cargo: инструмент управления пакетами для Rust, generics, traits, обработка ошибок и многое другое.

Rustlings

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

Упражнение Rust Track

rust

Трек Rust на Exercism содержит более 100 упражнений, которые помогут вам изучить и проверить свое понимание Rust. Exercism – это бесплатная платформа, где вы можете получить наставничество от опытных программистов, а также кодить самостоятельно, выполняя упражнения.

Ultimate Rust Crash Course

image-68

Ultimate Rust Crash Course, преподаваемый Натаном Стоксом на Udemy, охватывает следующее:

  • Основы программирования на языке Rust
  • Система модулей в Rust
  • Типы данных и поток управления
  • Справка и заимствование
  • Структуры, черты и коллекции

Ultimate Rust 2

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

  • Закрытия
  • Итераторы
  • Обработка ошибок
  • Модульное и интеграционное тестирование
  • Ведение журнала, многопоточность и каналы

Rust lang: Полное руководство для начинающих 2023

image-69

Этот курс Udemy, который ведет Каталин Стефан, представляет собой всеобъемлющий курс по программированию на языке Rust. Некоторые из рассматриваемых тем включают:

  • Основы Rust
  • Типы данных, управляющие структуры
  • Функции, черты
  • Управление памятью
  • Concurrency

Заключение

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