Vấn đề
Rust xử lý các module khác với các ngôn ngữ như Python hay JavaScript. Trong Rust, từ khóa mod không chỉ đơn thuần là import mã nguồn; nó khai báo rằng một module đang tồn tại. Khi bạn viết mod auth; trong tệp main.rs, bạn đang yêu cầu trình biên dịch đi tìm một tệp chứa mã nguồn cho module auth. Nếu trình biên dịch tìm kiếm trong các thư mục dự kiến mà không thấy gì, nó sẽ kích hoạt lỗi error[E0583].
Hãy coi lỗi này như một sự kết nối bị thất lạc. Bạn đã thông báo rằng một phần mới của chương trình hiện hữu, nhưng bạn lại chưa cung cấp cho trình biên dịch tệp vật lý để chứng minh điều đó. Điều này thường xảy ra khi bạn chuyển mã nguồn từ một tệp main.rs dài 200 dòng sang một tệp riêng biệt lần đầu tiên.
error[E0583]: file not found for module `my_module`
help: to create the module `my_module`, create file "src/my_module.rs" or "src/my_module/mod.rs"
Giải pháp nhanh
Đầu ra của trình biên dịch thực tế đã cung cấp một lộ trình để khắc phục. Nó gợi ý hai đường dẫn tệp cụ thể. Tùy thuộc vào cách bạn muốn tổ chức mã nguồn, hãy chọn một trong hai cấu trúc dưới đây.
1. Cách tiếp cận phẳng (Khuyến nghị cho hầu hết các trường hợp)
Rust hiện đại (Phiên bản 2018 trở về sau) ưu tiên giữ các module dưới dạng các tệp độc lập trong thư mục src/. Nếu module của bạn tên là auth, chỉ cần tạo tệp auth.rs.
Cấu trúc dự án:
my_project/
├── Cargo.toml
└── src/
├── main.rs
└── auth.rs <-- Tạo tệp này
Bên trong main.rs, phần khai báo của bạn vẫn rất đơn giản:
mod auth; // Rust tự động tìm kiếm src/auth.rs
2. Cách tiếp cận theo thư mục (Dành cho các module phức tạp)
Đôi khi một module phát triển quá lớn so với một tệp duy nhất. Nếu module auth của bạn cần các module con (như auth::saml và auth::oauth), hãy sử dụng một thư mục. Tạo một thư mục tên là auth và đặt tệp mod.rs bên trong đó.
Cấu trúc dự án:
my_project/
├── Cargo.toml
└── src/
├── main.rs
└── auth/
└── mod.rs <-- Đây đóng vai trò là điểm bắt đầu của module
Rust coi src/auth/mod.rs tương đương với src/auth.rs.
Xử lý các Module lồng nhau
Độ phức tạp tăng lên khi bạn lồng các module vào nhau. Giả sử bạn có một module database với một connector cụ thể: db::connector.
Nếu bạn khai báo mod connector; bên trong src/db.rs, trình biên dịch sẽ mong đợi tệp đó nằm tương đối với module db. Bạn có hai lựa chọn hợp lệ cho đường dẫn tệp:
- Lựa chọn A:
src/db/connector.rs(Phong cách hiện đại, gọn gàng hơn) - Lựa chọn B:
src/db/connector/mod.rs(Phong cách phân cấp cũ hơn)
Một sai lầm phổ biến là đặt connector.rs trực tiếp trong thư mục src/. Điều này sẽ thất bại. Rust yêu cầu các module con phải nằm trong một thư mục con được đặt tên theo module cha của chúng.
Danh sách kiểm tra gỡ lỗi phổ biến
Chú ý các phần mở rộng bị ẩn
Hãy xác nhận tệp của bạn kết thúc chính xác bằng đuôi .rs. Các trình soạn thảo văn bản cơ bản đôi khi tự ý thêm đuôi .txt vào cuối. Trên Windows, một tệp tên là auth.rs.txt có thể hiển thị là auth.rs nếu bạn đang bật chế độ "Hide extensions for known file types" (Ẩn phần mở rộng của các loại tệp đã biết). Nếu bạn nghi ngờ điều này, hãy kiểm tra tên tệp qua terminal bằng lệnh ls hoặc dir.
Tôn trọng tính phân biệt chữ hoa chữ thường
Rust phân biệt nghiêm ngặt chữ hoa chữ thường. Nếu mã của bạn ghi là mod Database; nhưng tệp của bạn tên là database.rs, trình biên dịch sẽ báo lỗi trên Linux và macOS. Các hệ điều hành này sử dụng hệ thống tệp phân biệt chữ hoa chữ thường. Để tránh rắc rối, hãy luôn sử dụng snake_case cho cả tên tệp và khai báo module.
Giữ các khai báo ở cấp cao nhất
Mặc dù Rust cho phép bạn khai báo các module bên trong các hàm, nhưng điều này hiếm khi là một ý hay. Làm như vậy sẽ tạo ra các quy tắc phân giải đường dẫn gây nhầm lẫn. Hãy kiên trì với việc đặt các câu lệnh mod ở đầu các tệp main.rs hoặc lib.rs của bạn.
Xác minh việc khắc phục
Đừng chờ đợi quá trình build hoàn tất để xem bạn đã sửa được lỗi hay chưa. Thay vào đó, hãy chạy một kiểm tra nhanh:
cargo check
Lệnh này phân tích mã của bạn mà không tốn công sức tạo ra một tệp thực thi. Nó thường hoàn thành trong chưa đầy 2 giây đối với các dự án nhỏ. Nếu lỗi vẫn còn, hãy so sánh đường dẫn trong thông báo lỗi với đường dẫn tệp thực tế của bạn từng ký tự một. Nếu trình biên dịch báo rằng nó muốn src/api/routes.rs, hãy đảm bảo bạn không vô tình đặt nó trong src/routes.rs.
Những điểm chính cần lưu ý
modlà một lời khai báo, không đơn thuần là import. Nó yêu cầu Rust tìm kiếm một tệp.- Hệ thống tệp của bạn phải phản chiếu hoàn hảo hệ thống phân cấp module.
- Ưu tiên phong cách
name.rsthay vìname/mod.rsđể có bố cục dự án gọn gàng hơn. - Luôn sử dụng
snake_casecho tên tệp để duy trì tính tương thích đa nền tảng.

