【问题标题】:Expected struct Config, found () while using process::exit预期结构配置,在使用 process::exit 时找到 ()
【发布时间】:2026-01-14 05:55:01
【问题描述】:

我是 Rust 的新手,正在阅读官方书籍。我正在研究一个简单的 grep 示例,并希望创建一个可以在不同地方使用的 exit 函数。不幸的是,在 unwrap_or_else 的闭包中使用此函数会导致编译错误。我不清楚这是为什么,因为当我直接在闭包中使用函数的内容时,它会起作用。

这是我的main.rs 文件:

use std::env;
use std::fs;
use std::process;
use std::error::Error;
use std::fmt::Display;

struct Config{
    query: String,
    filename: String,
}

impl Config {
    fn new(input: &[String]) -> Result<Config, &'static str> {
        if input.len() < 3 {
            return Err("Not enough arguments provided.");
        }
        let query = input[1].clone();
        let filename = input[2].clone();

        Ok(Config { query, filename })
    }
}

fn run(cfg: Config) -> Result<(), Box<dyn Error>> {
    let contents = fs::read_to_string(&cfg.filename)?;
    contents.find(&cfg.query).expect("Corrupted text file.");

    Ok(())
}

fn exit<T: Display>(msg: &str, err: T) {
    println!("{}: {}", msg, err);
    process::exit(1);
}

fn main() {
    let args: Vec<String> = env::args().collect();
    println!("{:?}", args);

    let cfg = Config::new(&args).unwrap_or_else(|err| {
        exit("Problem parsing arguments", err);
    });
    
    if let Err(err) = run(cfg) {
        exit("Application error", err);
    }
}

这是编译错误:

error[E0308]: mismatched types
  --> src\main.rs:41:55
   |
41 |       let cfg = Config::new(&args).unwrap_or_else(|err| {
   |  _______________________________________________________^
42 | |         exit("Problem parsing arguments", err);
43 | |     });
   | |_____^ expected struct `Config`, found `()`

当我将 Config::new(&amp;args).unwrap_or_else 闭包更改为此时,它可以工作:

let cfg = Config::new(&args).unwrap_or_else(|err| {
    println!("Problem parsing arguments: {}", err);
    process::exit(1);
});

【问题讨论】:

    标签: error-handling rust closures traits


    【解决方案1】:

    您需要指定您的 exit() 函数永远不会返回,即添加 -&gt; !

    这些函数称为“diverging functions”。

    fn exit<T: Display>(msg: &str, err: T) -> ! {
        println!("{}: {}", msg, err);
        process::exit(1);
    }
    

    但是,您应该小心使用process::exit()。因为它会终止当前进程,并且不会调用析构函数。

    为确保处理析构函数,您应该改为执行以下操作:

    fn main() {
        std::process::exit(match run() {
            Ok(_) => 0,
            Err(code) => code,
        });
    }
    
    fn run() -> Result<(), i32> {
        // Application logic here, i.e. what you'd otherwise have had in `main()`
    
        Ok(())
    }
    

    该示例是 process::exit() 文档中的示例的小修改版本。

    【讨论】:

    【解决方案2】:

    要添加到vallentin's answer,这是不使用process::exit 的更惯用的版本:

    use std::env;
    use std::error::Error;
    use std::fmt::Display;
    use std::fs;
    use std::process;
    
    struct Config {
        query: String,
        filename: String,
    }
    
    impl Config {
        fn new(input: &[String]) -> Result<Config, &'static str> {
            if input.len() < 3 {
                return Err("Not enough arguments provided.");
            }
            let query = input[1].clone();
            let filename = input[2].clone();
    
            Ok(Config { query, filename })
        }
    }
    
    fn run(cfg: Config) -> Result<(), Box<dyn Error>> {
        let contents = fs::read_to_string(&cfg.filename)?;
        // convert Option to a Result so we can use `?`
        contents.find(&cfg.query).ok_or("Corrupted text file.")?;
        Ok(())
    }
    
    // you can return a Result from main and Rust will
    // print the error to the user if there is one
    fn main() -> Result<(), Box<dyn Error>> {
        let args: Vec<String> = env::args().collect();
        println!("{:?}", args);
    
        // use `?` instead of `exit` function
        let cfg = Config::new(&args)?;
        run(cfg)?;
        Ok(())
    }
    

    playground

    【讨论】:

      【解决方案3】:

      我也陷入了困境。需要导入流程库:

      use std::process;
      

      edit:第二次看你确实导入了它。对于遇到这个问题的其他人,那是我的。我遇到了同样的错误。

      【讨论】: