Как подключить модуль из другого файла в том же проекте на Rust?
Основная проблема: видимость (приватность) элементов модуля
Вы почти всё сделали правильно, но в Rust по умолчанию всё в модулях приватно. Функция add в math.rs не помечена как pub, поэтому она недоступна за пределами модуля. Исправьте это:
// src/math.rs
pub fn add(x: i32, y: i32) -> i32 {
x + y
}
После этого ваш main.rs будет работать без ошибок. Ключевое слово pub делает функцию публичной и доступной для других модулей.
Как работает система модулей в Rust
В Rust нет отдельного понятия "файл как модуль" — файловая система автоматически отображается на модули:
- Файл
src/main.rs— корневой модуль крейта (если вы создаёте исполняемый файл). - Файл
src/math.rs— модульmath, дочерний по отношению к корневому. - Объявление
mod math;вmain.rsсообщает компилятору: "ищи файлmath.rs(илиmath/mod.rs) и загрузи его как модуль".
Полный пример правильной структуры
Допустим, вы хотите вынести несколько функций в отдельный модуль utils. Создайте файл src/utils.rs:
// src/utils.rs
pub fn greet(name: &str) -> String {
format!("Hello, {}!", name)
}
pub fn double(x: i32) -> i32 {
x * 2
}
Затем в main.rs подключите модуль и используйте его:
// src/main.rs
mod utils; // объявляем модуль
fn main() {
let greeting = utils::greet("Alice");
println!("{}", greeting);
let result = utils::double(10);
println!("Double: {}", result);
}
Что НЕ нужно делать
- Не нужно изменять
Cargo.toml— модули в пределах одного крейта не требуют дополнительных настроек. - Не используйте
useдля импорта модулей —useнужен для импорта имён (функций, типов) из модуля, а не для объявления самого модуля. - Не забывайте про
pub— если функция/структура не публичная, она останется приватной.
Как правильно использовать use
После объявления mod math; вы можете сократить вызовы с помощью use:
// src/main.rs
mod math;
use math::add; // импортируем функцию
fn main() {
let result = add(5, 3); // теперь можно вызывать без префикса math::
println!("Result: {}", result);
}
Также можно импортировать несколько элементов:
use math::{add, subtract};
Вложенные модули (папки)
Если у вас сложная структура, используйте папки. Например, для модуля utils/helpers.rs:
- Создайте папку
src/utils/. - Поместите в неё файл
helpers.rsс публичными функциями. - Создайте файл
src/utils/mod.rs(или используйтеsrc/utils.rsкак корень модуля) и объявите в нём дочерний модуль:// src/utils/mod.rs pub mod helpers; - В
main.rsобъявите внешний модуль:// src/main.rs mod utils; use utils::helpers::some_function;
Теперь ваш код будет организован и легко расширяем. Главное правило: каждый файл — это модуль, а mod объявляет связь между ними.
Альтернативный подход: модули внутри одного файла
Если вы не хотите создавать отдельные файлы, Rust позволяет определять вложенные модули прямо в main.rs. Это удобно для небольших проектов или прототипов:
// src/main.rs
mod math {
pub fn add(x: i32, y: i32) -> i32 {
x + y
}
pub fn subtract(x: i32, y: i32) -> i32 {
x - y
}
}
fn main() {
let sum = math::add(10, 5);
let diff = math::subtract(10, 5);
println!("Sum: {}, Diff: {}", sum, diff);
}
Этот метод позволяет быстро организовать код без создания дополнительных файлов. Однако для больших проектов лучше использовать отдельные файлы — это улучшает читаемость и упрощает навигацию.
Когда использовать файлы, а когда встроенные модули?
- Отдельные файлы — для модулей с большим количеством кода (100+ строк) или которые будут переиспользоваться.
- Встроенные модули — для небольших вспомогательных функций, тестовых модулей или когда код тесно связан с основным.
Также помните: если вы используете отдельные файлы, вы всё равно можете объявлять внутри них вложенные модули. Например, в math.rs можно добавить:
// src/math.rs
pub fn add(x: i32, y: i32) -> i32 { x + y }
pub mod advanced {
pub fn multiply(x: i32, y: i32) -> i32 { x * y }
}
Тогда в main.rs вы сможете вызывать math::advanced::multiply(2, 3).
Ответов пока нет.
Войдите чтобы оставить ответ