
Привет, Хабр!
Rust - это язык, который становится плюс-минус более популярным в последние годы благодаря своей высокой производительности и безопасности. Он был разработан Mozilla и сообществом разработчиков с целью предоставить инструмент для системного программирования, который позволяет избегать многих распространенных ошибок, связанных с управлением памятью.
В этой статье рассмотрим основы Rust.
Настройка окружения
На сайте раста есть инструкции по установке Rust на любую ОС. Процесс установки прост и интуитивно понятен и ее может выполнить любой школьник.
После установки Rust и Cargo, убедимся, что они работают правильно. Открываем терминал и юзаем команду:
rustc --version
Команда должна вернуть текущую версию компилятора Rust, установленную на ПК.
Проверяем версию Cargo:
cargo --version
Если обе команды успешно возвращают версии инструментов, то все ок.
Создание первой программы на Rust
Для создания нового проекта на Rust, можно воспользоваться командой cargo new hello_rust
. Cargo - это универсальный инструмент для управления зависимостями в расте. Команда создаст каталог с именем hello_rust
, который будет содержать структуру проекта Rust. Внутри этого каталога лежит файл main.rs
, в нем напишем код:
По классике поздорваемся с миром:
fn main() {
println!("Hello, World!");
}
После этого можно перейти в терминал, перейти в каталог проекта и выполнить команду cargo run
Синтаксис Rust
Переменные и их мутабельность
Одна из особенностей Rust - это строгая система типов, которая помогает избежать множества ошибок на этапе компиляции:
let x = 42; // Неизменяемая переменная
let mut y = 24; // Изменяемая переменная
let
используется для объявления переменных. Первая переменная x
неизменяема, что означает, что после присвоения значения 42, она не может быть изменена. Вторая переменная y
объявлена как изменяемая, поэтому можно изменять ее значение.
Операторы и контроль потока
Rust поддерживает все базовые операторы, включая арифметические, логические и сравнительные операторы:
fn ariph() {
let a = 10;
let b = 3;
let sum = a + b; // Сложение
let difference = a - b; // Вычитание
let product = a * b; // Умножение
let quotient = a / b; // Деление
let remainder = a % b; // Остаток от деления
fn logic() {
let is_sunny = true;
let is_warm = false;
let is_good_weather = is_sunny && is_warm; // Логическое И
let is_raining = !is_sunny; // Логическое НЕ
}
fn sravn() {
let x = 5;
let y = 10;
let is_equal = x == y; // Равно
let is_not_equal = x != y; // Не равно
let is_greater = x > y; // Больше
let is_less = x < y; // Меньше
let is_greater_or_equal = x >= y; // Больше или равно
let is_less_or_equal = x <= y; // Меньше или равно
}
Условные операторы: if, else if, else
fn main() {
let age = 25;
if age < 18 {
println!("Вы несовершеннолетний");
} else if age >= 18 && age < 65 {
println!("Вы взрослый");
} else {
println!("Вы пенсионер");
}
}
Циклы: for, while
Циклы позволяют нам выполнять определенные блоки кода несколько раз. В Rust есть два основных типа циклов: for
и while
:
fn main() {
// Цикл for
for i in 1..=5 {
println!("Итерация {}", i);
}
// Цикл while
let mut counter = 0;
while counter < 3 {
println!("Повторение {}", counter);
counter += 1;
}
}
В for
используем диапазон чисел 1..=5
для выполнения блока кода пять раз. В случае цикла while
, выполняем блок кода, пока значение переменной counter
меньше 3, и увеличиваем его после каждой итерации.
Match-выражения
Match-выражения позволяют сравнивать значение с несколькими возможными вариантами и выполнять соответствующий блок кода:
fn main() {
let language = "Rust";
match language {
"Rust" => println!("Вы выбрали Rust - отличный выбор!"),
"Python" | "JavaScript" => println!("Тоже хорошие языки!"),
_ => println!("Неизвестный язык программирования"),
}
}
Если значение соответствует "Rust", выводим сообщение о выборе Rust. Если оно соответствует "Python" или "JavaScript", выводим общее сообщение. В противном случае, используем _
, чтобы обработать все остальные значения.
Объявление функций
fn main() {
// Вызов функции
greet("Alice");
// Вызов функции с возвращаемым значением
let result = add(3, 5);
println!("Сумма: {}", result);
}
// Объявление функции без возвращаемого значения
fn greet(name: &str) {
println!("Привет, {}!", name);
}
// Объявление функции с возвращаемым значением
fn add(a: i32, b: i32) -> i32 {
a + b
}
Параметры функций
fn main() {
let a = 5;
let b = 3;
let sum = add(a, b);
println!("Сумма: {}", sum);
}
fn add(x: i32, y: i32) -> i32 {
x + y
}
add
принимает два параметра x
и y
, их значения передаются из функции main
при вызове функции add
.
Возвращаемые значения функций
Возвращаемый тип указывается после параметров функции и определяет тип данных, который функция вернет:
fn main() {
let result = multiply(4, 6);
println!("Произведение: {}", result);
}
fn multiply(a: i32, b: i32) -> i32 {
a * b // Это выражение будет возвращено из функции
}
multiply
возвращает произведение двух чисел типа i32
.
Структуры данных
Целые числа
let integer: i32 = 42; // 32-битное целое число со знаком
let unsigned_integer: u64 = 100; // 64-битное целое число без знака
Числа с плавающей точкой
let float: f32 = 3.14159265359; // 32-битное число с плавающей точкой
let double: f64 = 2.71828182845; // 64-битное число с плавающей точкой (по умолчанию)
Булевы значения
let is_rust_cool: bool = true; // Логическое значение true
let is_open_source: bool = false; // Логическое значение false
Символы и строки
let char_type: char = 'A'; // Символ
let string_type: &str = "Hello, Rust!"; // Строка (неизменяемая)
Векторы
В Rust векторы можно создавать и изменять в размере по мере необходимости:
fn main() {
// Создание вектора целых чисел
let mut numbers: Vec<i32> = Vec::new();
// Добавление элементов в вектор
numbers.push(42);
numbers.push(24);
numbers.push(12);
// Доступ к элементам вектора
let first = numbers[0];
// Итерация по вектору
for num in &numbers {
println!("Число: {}", num);
}
// Размер вектора
let length = numbers.len();
// Удаление элемента из вектора
let removed = numbers.pop();
}
Создали пустой вектор numbers
для хранения целых чисел, добавили элементы в него с помощью метода push
, получили доступ к элементу по индексу и прошлись по всем элементам вектора.
Массивы
fn main() {
// Создание массива строк
let colors: [&str; 3] = ["Red", "Green", "Blue"];
// Доступ к элементам массива
let first_color = colors[0];
// Итерация по массиву
for color in &colors {
println!("Цвет: {}", color);
}
// Размер массива (известен на этапе компиляции)
let length = colors.len();
}
Создали массив colors
, содержащий три строки. Массивы в Rust имеют фиксированный размер, который задается при объявлении.
Какой контейнер выбрать - вектор или массив? Выбор зависит от конкретной задачи. Если нужна динамичность и возможность изменять размер данных во времени, то векторы оч. хорошо подходят. Если же вы знаете точный размер данных заранее, то массивы более адекватным выбором.
Структуры
Структуры - это способ объединить несколько переменных разных типов в одну логическую единицу:
// Определение структуры Point
struct Point {
x: f64,
y: f64,
}
fn main() {
// Создание экземпляра структуры Point
let origin = Point { x: 0.0, y: 0.0 };
// Доступ к полям структуры
println!("Координаты точки: ({}, {})", origin.x, origin.y);
}
Определили структуру Point
, содержащую два поля типа f64
- x
и y
. Затем создали экземпляр структуры origin
и получили доступ к полям.
Перечисления
// Определение перечисления Animal
enum Animal {
Dog,
Cat,
Bird,
}
fn main() {
// Использование перечисления
let pet = Animal::Dog;
// Проверка значения перечисления
match pet {
Animal::Dog => println!("Это собачка!"),
Animal::Cat => println!("Это котик!"),
Animal::Bird => println!("Это птиц!"),
}
}
Определили перечисление Animal
, которое может принимать одно из трех значений. Затем создали переменную pet
и с помощью match
сравнили ее значение с вариантами перечисления.
Если нужно организовать данные с разными полями, то выбор здесь - структура. Если идет работа с вариативными данными или определяете состояния объекта, то перечисления придутся как нельзя кстати.
Также в Rust реализовано хорошее и безопасное управление памятью, у меня есть статья на эту тему: как работает управление памятью в Rust без сборщика мусора.
В целом Rust очень даже хороший ЯП и набирает свою популярность.
Подробнее про Rust и другие языки программирования, мои друзья из OTUS рассказывают в рамках практических онлайн-курсов. С полным списком курсов можно ознакомиться в каталоге.