Перейти к основному содержимому

Первая программа "Hello, World!"

В этой главе мы создадим вашу первую полноценную программу на Rust, разберём её структуру и познакомимся с основными элементами синтаксиса языка. Традиционно первая программа выводит приветствие "Hello, World!" — и мы не будем нарушать эту традицию!

Создание проекта

Начнём с создания нового Rust-проекта с помощью Cargo:

Создание нового проекта
# Создаём проект
cargo new hello_world
cd hello_world

# Просматриваем структуру
ls -la

Результат выполнения команд:

Created binary (application) `hello_world` package

hello_world/
├── Cargo.toml
├── src/
│ └── main.rs
└── .gitignore
Что создал Cargo?
  • Cargo.toml — файл конфигурации проекта (манифест)
  • src/main.rs — главный исходный файл программы
  • .gitignore — настройки для системы контроля версий Git

Анализ структуры проекта

Файл Cargo.toml

Откройте файл Cargo.toml — это сердце любого Rust-проекта:

Cargo.toml
[package]
name = "hello_world"
version = "0.1.0"
edition = "2021"

[dependencies]

Основная информация о проекте:

  • name — имя пакета (используется при публикации)
  • version — версия в формате Semantic Versioning
  • edition — версия языка Rust (2015, 2018, 2021)
Расширенная секция [package]
[package]
name = "hello_world"
version = "0.1.0"
edition = "2021"
authors = ["Ваше Имя <email@example.com>"]
description = "Моя первая программа на Rust"
license = "MIT"

Файл main.rs

Теперь откройте главный файл программы src/main.rs:

src/main.rs
fn main() {
println!("Hello, world!");
}

Эта простая программа содержит все ключевые элементы Rust-приложения!

Разбор синтаксиса "Hello, World!"

Функция main

Анатомия функции main
fn main() {
println!("Hello, world!");
}
//│ │ │ │ │
//│ │ │ │ └─ Закрывающая скобка функции
//│ │ │ └─ Содержимое функции (тело)
//│ │ └─ Открывающая скобка функции
//│ └─ Имя функции
//└─ Ключевое слово объявления функции

Особенности функции main:

🚀 Точка входа

main — это специальная функция, с которой начинается выполнение программы

📝 Синтаксис

fn — ключевое слово для объявления функций

🔧 Параметры

Пустые скобки () означают, что функция не принимает параметры

↩️ Возврат

Функция ничего не возвращает (тип () — unit type)

Макрос println!

Анализ println!
println!("Hello, world!");
//│ │ │ │ │
//│ │ │ │ └─ Точка с запятой (завершение выражения)
//│ │ │ └─ Закрывающая кавычка строки
//│ │ └─ Строковый литерал
//│ └─ Открывающая скобка макроса
//└─ Восклицательный знак указывает на макрос
Макрос vs Функция

println! — это макрос, а не функция. Восклицательный знак ! после имени всегда указывает на макрос в Rust.

Возможности println!:

Простой вывод текста
fn main() {
println!("Hello, world!");
println!("Привет, мир!");
println!("Это вторая строка");
}

Вывод:

Hello, world!
Привет, мир!
Это вторая строка

Запуск программы

Теперь запустим нашу программу несколькими способами:

Способ 1: Через Cargo (рекомендуется)

Запуск через Cargo
# Компиляция и запуск одной командой
cargo run

Что происходит под капотом:

   Compiling hello_world v0.1.0 (/path/to/hello_world)
Finished dev [unoptimized + debuginfo] target(s) in 1.23s
Running `target/debug/hello_world`
Hello, world!

Способ 2: Компиляция и запуск отдельно

Раздельная компиляция и запуск
# Только компиляция
cargo build

# Запуск скомпилированного файла
./target/debug/hello_world

Способ 3: Через компилятор rustc

Прямая компиляция
# Компиляция одного файла
rustc src/main.rs

# Запуск
./main
Какой способ выбрать?
  • cargo run — для разработки (удобно и быстро)
  • cargo build — когда нужно только скомпилировать
  • rustc — для простых однофайловых программ

Режимы сборки

Rust поддерживает разные режимы сборки проекта:

Режим по умолчанию для разработки:

Отладочная сборка (debug)
cargo build
# или
cargo run

Характеристики:

  • Быстрая компиляция
  • Большой размер файла
  • Включена отладочная информация
  • Медленное выполнение
  • Файл: target/debug/hello_world

Сравнение производительности:

Демонстрация разницы
# Отладочная версия
time ./target/debug/hello_world

# Релизная версия
time ./target/release/hello_world

Модификация программы

Давайте улучшим нашу первую программу:

Версия 2: С переменными

src/main.rs - версия с переменными
fn main() {
let greeting = "Hello";
let target = "World";

println!("{}, {}!", greeting, target);
}

Версия 3: Интерактивная

src/main.rs - интерактивная версия
use std::io;

fn main() {
println!("Как вас зовут?");

let mut name = String::new();
io::stdin()
.read_line(&mut name)
.expect("Не удалось прочитать строку");

println!("Привет, {}!", name.trim());
}
Новые концепции

В интерактивной версии появились новые элементы:

  • use — импорт модулей
  • let mut — изменяемая переменная
  • String::new() — создание строки
  • expect() — обработка ошибок

Версия 4: С аргументами командной строки

src/main.rs - с аргументами
use std::env;

fn main() {
let args: Vec<String> = env::args().collect();

if args.len() > 1 {
println!("Привет, {}!", args[1]);
} else {
println!("Hello, World!");
println!("Использование: {} <имя>", args[0]);
}
}

Запуск:

cargo run Анна
# Вывод: Привет, Анна!

Структура файловой системы проекта

После компиляции структура проекта выглядит так:

hello_world/
├── Cargo.toml # Манифест проекта
├── Cargo.lock # Файл блокировки зависимостей (создаётся автоматически)
├── src/ # Исходный код
│ └── main.rs
├── target/ # Результаты компиляции
│ ├── debug/ # Отладочные сборки
│ │ ├── hello_world # Исполняемый файл
│ │ └── deps/ # Скомпилированные зависимости
│ └── release/ # Релизные сборки
│ └── hello_world
└── .gitignore
Важно знать

Папка target/ содержит временные файлы компиляции и может быть удалена в любой момент. Cargo пересоздаст её при следующей сборке.

Полезные команды Cargo

Теперь, когда у нас есть рабочий проект, познакомимся с основными командами:

КомандаОписаниеПример
cargo newСоздать новый проектcargo new my_app
cargo buildСкомпилировать проектcargo build --release
cargo runСкомпилировать и запуститьcargo run -- arg1 arg2
cargo checkПроверить код без компиляцииcargo check
cargo cleanОчистить папку target/cargo clean
cargo testЗапустить тестыcargo test
cargo docСгенерировать документациюcargo doc --open

Практические примеры

Полезные команды для разработки
# Быстрая проверка синтаксиса (без создания исполняемого файла)
cargo check

# Подробный вывод процесса компиляции
cargo build --verbose

# Очистка и пересборка проекта
cargo clean && cargo build

# Запуск с аргументами
cargo run -- --help

# Просмотр информации о проекте
cargo metadata --no-deps --format-version 1

Распространённые ошибки и их исправление

Ошибка 1: Забыта точка с запятой

❌ Неправильно
fn main() {
println!("Hello, world!") // Отсутствует ;
}

Ошибка компилятора:

error: expected `;`, found `}`

✅ Правильно:

fn main() {
println!("Hello, world!"); // Добавлена ;
}

Ошибка 2: Неправильный синтаксис функции

❌ Неправильно
function main() {  // Использовано 'function' вместо 'fn'
println!("Hello, world!");
}

✅ Правильно:

fn main() {  // Используется 'fn'
println!("Hello, world!");
}

Ошибка 3: Неправильное использование кавычек

❌ Неправильно
fn main() {
println!('Hello, world!'); // Одинарные кавычки для строки
}

✅ Правильно:

fn main() {
println!("Hello, world!"); // Двойные кавычки для строки
}
Совет

Одинарные кавычки ' в Rust используются только для символов (char), а двойные кавычки " — для строк (string literals).

Понимание процесса компиляции

Что происходит при выполнении cargo run

  1. Чтение Cargo.toml — Cargo анализирует конфигурацию проекта
  2. Разрешение зависимостей — загружаются и компилируются библиотеки
  3. Компиляция исходного кода — rustc преобразует Rust-код в машинный код
  4. Линковка — создаётся финальный исполняемый файл
  5. Запуск — выполняется скомпилированная программа

Промежуточные файлы

Изучение содержимого target/
# Посмотрим, что создал компилятор
find target/debug -name "*hello*" -type f

# Информация о скомпилированном файле
file target/debug/hello_world
size target/debug/hello_world

Заключение

В этой главе мы:

Создали первый Rust-проект с помощью Cargo ✅ Разобрали структуру простой программы ✅ Изучили синтаксис функции main и макроса println! ✅ Научились компилировать и запускать программы ✅ Познакомились с базовыми командами Cargo ✅ Рассмотрели типичные ошибки и их исправление

Теперь вы понимаете базовую структуру Rust-программы и готовы к изучению более сложных концепций языка!

Что дальше?

В следующей главе: "Знакомство с системой сборки Cargo" — мы углубимся в возможности Cargo, научимся работать с зависимостями и настраивать проекты.


Практические задания

  1. Создайте программу, которая выводит ваше имя и возраст
  2. Модифицируйте программу для вывода таблицы умножения на 5
  3. Создайте программу, которая принимает два аргумента командной строки и выводит их в обратном порядке

Вопросы для самопроверки

  1. Чем отличается макрос от функции в Rust?
  2. Что произойдёт, если удалить восклицательный знак из println!?
  3. В чём разница между debug и release сборкой?
  4. Какие файлы создаёт команда cargo new?

Полезные ссылки