Как подключить модуль из другого файла в том же проекте на Rust?
Как правильно подключать модули в Rust: пошаговое руководство
Проблема, с которой вы столкнулись, очень типична для новичков. В Rust система модулей работает не так, как в Python или JavaScript. Давайте разберёмся по порядку.
Шаг 1. Объявление модуля с помощью mod
Когда вы пишете mod math_utils; в main.rs, вы говорите компилятору: "Ищи файл math_utils.rs (или папку math_utils/mod.rs) и загрузи его как модуль". Это правильный первый шаг. Но после этого функции внутри модуля не становятся автоматически доступными — они находятся в пространстве имён модуля.
Исправленный main.rs:
// main.rs
mod math_utils; // Объявляем модуль
fn main() {
// Теперь нужно обращаться через имя модуля
let result = math_utils::add(5, 3);
println!("Result: {}", result);
}
Шаг 2. Публичность (pub)
Даже после этого код не скомпилируется. В Rust всё по умолчанию приватное. Функция add внутри модуля math_utils не видна снаружи. Нужно явно сделать её публичной:
// math_utils.rs
pub fn add(x: i32, y: i32) -> i32 { // Добавили pub
x + y
}
Шаг 3. Сокращение пути с помощью use
Если вам надоело каждый раз писать math_utils::add, используйте use:
// main.rs
mod math_utils;
use math_utils::add; // Импортируем функцию в текущую область видимости
fn main() {
let result = add(5, 3); // Теперь можно вызывать напрямую
println!("Result: {}", result);
}
Более сложная структура: подмодули и папки
Когда проект растёт, вы можете захотеть создать папку для модуля. Например, структура:
src/
├── main.rs
└── math/
├── mod.rs // Главный файл модуля math
└── advanced.rs // Дочерний модуль
В math/mod.rs:
// math/mod.rs
pub mod advanced; // Объявляем дочерний модуль
pub fn basic_add(x: i32, y: i32) -> i32 {
x + y
}
В math/advanced.rs:
pub fn fast_add(x: i32, y: i32) -> i32 {
x + y
}
В main.rs:
mod math; // Объявляем корневой модуль math
use math::basic_add;
use math::advanced::fast_add;
fn main() {
println!("Basic: {}", basic_add(1, 2));
println!("Fast: {}", fast_add(3, 4));
}
Важные правила
- Не нужно ничего менять в Cargo.toml. Cargo сам находит все
.rsфайлы в папкеsrc/. - Каждый файл — это модуль. Имя файла (без
.rs) становится именем модуля. - Точка входа —
main.rsилиlib.rs. Для бинарных проектов —main.rs, для библиотек —lib.rs. - Используйте
pubдля экспорта. Всё, что вы хотите сделать доступным снаружи модуля, должно быть помеченоpub. - Для папок используйте
mod.rs. Если вы создаёте папкуmy_module/, внутри должен быть файлmod.rs(или можно использоватьmy_module.rsкак корневой файл, но это новый синтаксис Rust 2018).
Теперь ваш код будет работать! Если у вас остались вопросы, не стесняйтесь задавать их в комментариях.
<<Альтернативный подход: использование crate:: и относительных путей
В дополнение к основному ответу, стоит упомянуть, что в Rust есть несколько способов ссылаться на модули, особенно когда у вас сложная иерархия.
Вместо того чтобы везде писать use, вы можете использовать абсолютные пути от корня крейта (crate):
// main.rs
mod math_utils;
fn main() {
// Абсолютный путь от корня проекта
let result = crate::math_utils::add(10, 20);
println!("{}", result);
}
Это особенно полезно в больших проектах, где вы находитесь глубоко внутри вложенных модулей. Ключевое слово crate обозначает корень вашего проекта (то есть main.rs или lib.rs).
Также есть относительные пути с ключевыми словами self (текущий модуль), super (родительский модуль) и crate (корень). Пример:
// Внутри math/advanced.rs
use super::basic_add; // super ведёт в math/mod.rs
pub fn complex_calc(x: i32) -> i32 {
basic_add(x, 10) * 2
}
Используйте тот стиль, который делает ваш код более читаемым и поддерживаемым. Для небольших проектов use в начале файла — это золотой стандарт.
Ответов пока нет.
Войдите чтобы оставить ответ