Как включить модуль из другого файла в Rust: от новичка до уверенного пользователя
Вы когда-нибудь писали код на Rust и вдруг понимали, что ваш main.rs превращается в гигантского монстра на 500 строк? Знакомо? Или, возможно, вы только начинаете изучать Rust и хотите понять, как правильно организовать код, разбив его на несколько файлов. Вопрос "How can I include a module from another file from the same project?" — один из самых популярных на Stack Overflow, и не зря. Модульная система Rust одновременно мощная и... немного неочевидная для новичков.
В этой статье мы разберем всё от А до Я: как создать модуль, как его подключить, какие есть подводные камни и как не наступить на грабли. Поехали!
Почему модули в Rust — это не просто "include"?
Если вы пришли из Python или JavaScript, вы привыкли к import или require. В Rust всё немного иначе. Здесь нет магического "подхвати файл и используй". Вместо этого Rust использует декларативную систему модулей. Вы должны явно сказать компилятору: "Эй, вот этот файл — часть моего проекта, и вот как он называется".
Основное правило, которое нужно запомнить: каждый файл — это модуль, но не каждый модуль — это файл. Звучит как загадка, да? Сейчас разберемся.
Структура проекта: с чего начать
Предположим, у вас есть проект с такой структурой:
my_project/
├── Cargo.toml
├── src/
│ ├── main.rs
│ ├── greetings.rs
│ └── utils/
│ ├── mod.rs
│ └── helpers.rs
Здесь greetings.rs — простой модуль, а utils/ — папка с модулем. Давайте научимся их подключать.
Способ 1: Подключение простого файла-модуля
Самый базовый случай. У вас есть greetings.rs с функцией:
// greetings.rs
pub fn say_hello() {
println!("Привет из модуля greetings!");
}
Чтобы использовать этот модуль в main.rs, нужно сделать две вещи:
- Объявить модуль с помощью ключевого слова
mod - Импортировать нужные элементы с помощью
use
// main.rs
mod greetings; // объявляем модуль
use greetings::say_hello; // импортируем функцию
fn main() {
say_hello(); // используем
}
Вот и всё! Rust автоматически ищет файл greetings.rs в той же папке, где лежит main.rs. Если файл найден — модуль подключен.
Важно: функция say_hello помечена как pub. Если забыть pub, компилятор скажет, что функция приватная и недоступна извне. Это одна из самых частых ошибок новичков.
Способ 2: Модуль в папке (mod.rs или lib.rs)
Когда ваш проект разрастается, удобно группировать модули в папки. Для этого используется файл mod.rs внутри папки. Он служит "точкой входа" в модуль.
Создадим папку utils/ и внутри неё mod.rs:
// utils/mod.rs
pub mod helpers; // объявляем вложенный модуль
Теперь создадим helpers.rs:
// utils/helpers.rs
pub fn do_something() {
println!("Делаем что-то полезное");
}
В main.rs подключаем так:
// main.rs
mod utils; // объявляем модуль utils (ищет utils/mod.rs)
use utils::helpers::do_something;
fn main() {
do_something();
}
Обратите внимание: mod utils; говорит Rust искать utils/mod.rs или utils.rs. Если найдёт mod.rs — отлично, если utils.rs — тоже подойдёт. Но нельзя иметь оба файла одновременно — компилятор запутается.
Способ 3: Современный подход (Rust 2018+)
Начиная с Rust 2018, вы можете использовать путь к модулю без mod.rs. Вместо utils/mod.rs можно создать utils.rs и папку utils/ рядом. Это называется "модуль с вложенными подмодулями".
Структура будет такой:
src/
├── main.rs
├── utils.rs
└── utils/
└── helpers.rs
В utils.rs пишем:
// utils.rs
pub mod helpers;
А в helpers.rs — тот же код. В main.rs ничего не меняется:
mod utils;
use utils::helpers::do_something;
Какой способ выбрать? Лично я рекомендую второй (с mod.rs), если вы новичок — он более наглядный и явный. Но оба работают отлично.
Частые ошибки и как их избежать
Давайте разберём топ-3 граблей, на которые наступают почти все:
1. "Модуль не найден" (file not found for module)
Вы написали mod my_module;, а Rust пишет: "не могу найти файл". Причины:
- Файл называется
my_module.rs, а неmyModule.rs(регистр важен!) - Файл лежит не в той папке. Для
mod my_module;вmain.rsфайл должен быть рядом:src/my_module.rs - Вы случайно создали
my_module.rsиmy_module/mod.rsодновременно — удалите один из них.
2. "Функция приватная" (function is private)
Вы импортировали модуль, но не можете вызвать функцию. Решение: добавьте pub перед функцией, структурой или полем.
// Неправильно
fn secret() {} // приватная
// Правильно
pub fn secret() {} // публичная
3. "Путь не найден" (unresolved import)
Вы написали use my_module::my_function;, а Rust не понимает, где my_function. Проверьте:
- Правильно ли объявлен модуль через
mod? - Не забыли ли
pubу самой функции? - Правильно ли написан путь? Если модуль вложен, путь должен быть полным:
utils::helpers::do_something.
Продвинутый пример: модули в библиотеке (lib.rs)
Блоги
Рекомендаций по книгам
Читайте также