Rust 错误 E0601:`main` function not found in crate(找不到 main 函数)
E0601 的意思是:Rust 想构建一个程序,却找不到程序从哪里开始。 每个 Rust 程序都从一个名字恰好叫 main 的函数开始,它写在 src/main.rs 的最外层。如果它不存在、拼错了,或者藏在某个模块里,你就会得到这个错误。从教程或库文档里复制代码片段时很容易碰到它,而且总是很快就能修好。(本页属于 Rust 编译错误详解系列。)
error[E0601]: `main` function not found in crate `main` --> src/main.rs:7:2 |7 | } // ❌ end of the file, and no `fn main` anywhere | ^ consider adding a `main` function to `src/main.rs`第一行的意思是“在 crate main 里找不到 main 函数”。标注建议你在 src/main.rs 里加一个 main 函数。
产生这个错误的程序是这样的:
fn total(prices: &[u32]) -> u32 { prices.iter().sum()}
fn average(prices: &[u32]) -> u32 { total(prices) / prices.len() as u32} // ❌ end of the file, and no `fn main` anywhere这个错误是什么意思
Section titled “这个错误是什么意思”^ 指着文件的最末尾,就在最后一个 } 后面。这看起来有点怪,但其实很合理:rustc 读完了整个文件,一直在找 fn main,到了结尾也没找到。没有哪一行写错了可以指出来;问题出在一行根本不存在的代码上。
错误信息里的 crate 名取决于你怎么构建。上面的输出来自 rustc src/main.rs,所以 crate 按文件名叫做 main。如果用 cargo run,你看到的就是 Cargo.toml 里的包名,比如 `main` function not found in crate `shop`。错误是同一个,修法也一样。
就像一部剧本,场景都写得很精彩,却没有“第一幕第一场”。演员都准备好了,可没人知道演出从哪里开始。
Rust 为什么要这样做
Section titled “Rust 为什么要这样做”Rust 的二进制程序(你可以运行的程序)需要一个固定的入口点。启动程序时,操作系统调用 main,其他所有代码都是因为 main 调用了它们才会运行。Rust 不会去猜:不会选文件里的第一个函数,不会选叫 start 的函数,也不会选 Main。名字必须恰好是全小写的 main,并且写在 crate 的最外层。
本身不是程序的代码,比如一组供其他代码使用的辅助函数,属于库。库没有 main,要写在 src/lib.rs 里。E0601 常常说明代码本身没问题,只是放进了错误类型的 crate 里。参见同时包含二进制 crate 和库 crate和快速开始。
修复 1:加上 main 函数(或者改正拼写)
Section titled “修复 1:加上 main 函数(或者改正拼写)”大多数时候选这个方法:你从别处复制了一些函数,或者先写了辅助函数,还没写 main。加上 fn main(),在里面调用你的代码:
fn total(prices: &[u32]) -> u32 { prices.iter().sum()}
fn average(prices: &[u32]) -> u32 { total(prices) / prices.len() as u32}
fn main() { // ✅ 程序从这里开始 let prices = [250, 199, 1200]; println!("总价:{} 分", total(&prices)); println!("平均:{} 分", average(&prices));}输出:
总价:1649 分平均:549 分已经有 main 了?那就检查一下拼写。fn Main()、fn mian() 或 fn main_() 都会报一模一样的 E0601,因为在 Rust 看来它们只是别的函数。名字区分大小写,而且它必须是一个函数:带括号的 fn main()。
修复 2:把 main 移出模块
Section titled “修复 2:把 main 移出模块”当错误信息里写着 the main function must be defined at the crate level(main 函数必须定义在 crate 的最外层)时选这个方法。你有一个 main,但它在某个 mod 里,所以它实际上是 app::main,而不是程序的入口点:
error[E0601]: `main` function not found in crate `main` --> src/main.rs:5:2 |5 | } | ^ the main function must be defined at the crate level (in `src/main.rs`) |note: here is a function named `main` --> src/main.rs:2:5 |2 | pub fn main() { // ❌ inside a module, not at the top level | ^^^^^^^^^^^^^ = note: you have one or more functions named `main` not defined at the crate level = help: consider moving the `main` function definitionsnote: 指出了那个叫 main 的函数在哪里,help: 建议你把它挪个位置。背后的程序:
mod app { pub fn main() { // ❌ inside a module, not at the top level println!("Starting the shop..."); }}把真正的 main 放到最外层。模块里的代码可以留在原处;给它起个更清楚的名字,比如 run,再从 main 里调用它:
mod app { pub fn run() { println!("Starting the shop..."); }}
fn main() { // ✅ 位于 src/main.rs 的最外层 app::run();}输出:
Starting the shop...其他文件里的模块也一样:src/app.rs 里的 pub fn main() 是 app::main,永远不会是入口点。参见模块。
修复 3:如果它本来就不是独立运行的,就做成库
Section titled “修复 3:如果它本来就不是独立运行的,就做成库”当这些代码是一组供其他代码使用的辅助函数,没有什么可以“运行”的时候,选这个方法。库没有 main。用 --lib 创建项目:
cargo new --lib cart # 创建 src/lib.rs:一个库,不需要 maincargo new shop # 创建带 fn main() 的 src/main.rs:一个程序把辅助函数放进 src/lib.rs,用 pub 标出其他代码可以使用的部分,然后用测试来检查它们,而不是用 cargo run:
pub fn total(prices: &[u32]) -> u32 { prices.iter().sum()}
#[cfg(test)]mod tests { use super::*;
#[test] fn adds_prices() { assert_eq!(total(&[3, 4]), 7); }}对库要运行 cargo build 或 cargo test。cargo run 在这里不管用;它会说 error: a bin target must be available for `cargo run`,这是 Cargo 在告诉你“这个包里没有程序”。如果两者都想要,就在 src/lib.rs 旁边加一个 src/main.rs。它通过包名来使用这个库:
fn main() { let sum = cart::total(&[250, 199, 1200]); println!("total: {} cents", sum);}现在 cargo run 会打印 total: 1649 cents。参见同时包含二进制 crate 和库 crate和测试。
粘贴文档或教程里的代码片段。 很多示例只展示一个函数或一个 struct,而不是完整的程序。把它们粘贴进 src/main.rs,就会报 E0601。修复:把真正做事的那几行包进 fn main() { ... },函数和结构体留在外面。(Rust Playground 会发现缺少 main,并提供只构建、不运行代码的选项,所以在那里你通常看不到这个错误。)
编辑器把 main.rs 的最后一行标红。 rust-analyzer 会在后台运行 cargo check,所以你还在写辅助函数时,最后一行就会显示 E0601。这没关系:一加上 fn main(),标记就会消失。
src/bin/ 里的其他程序。 src/bin/ 里的每个文件,比如 src/bin/import.rs,都是一个独立的程序,每个都需要自己的 fn main()。修复:给那个文件加上 main,或者把共用的代码移进 src/lib.rs。参见下面 Cargo 目标的链接。
- E0425:cannot find value in this scope:程序里别处的名字拼错了,比如调用了
totl()。 - E0433:failed to resolve:
main.rs找不到某个模块或库 crate,比如cart::total里的包名写错了。 - E0603:item is private:
main找到了库里的函数,但它不是pub的。 - E0463:can’t find crate:你
use的 crate 不在Cargo.toml里。 - 所有编译错误详解
小测验
1. 你的 src/main.rs 里写的是 fn Main() { ... }。cargo run 会说什么?
2. 你在写一些供其他代码使用的辅助函数,没有什么需要运行。正确的做法是什么?
3. rustc 说“the main function must be defined at the crate level”。哪里出了问题?
得分: 0 / 3
- E0601 — Rust error codes index(英文):这个错误的官方解释。
- Hello, World! — Rust 程序设计语言:你的第一个
main函数,以及为什么每个程序都从它开始。 - 包和 crate — Rust 程序设计语言:二进制 crate 和库 crate,
src/main.rs和src/lib.rs的区别。 - Cargo Targets — The Cargo Book(英文):库、二进制程序、
src/bin/,以及 Cargo 怎样找到它们。 - Main functions — The Rust Reference(英文):关于
main的准确规则,包括它可以定义在哪里。