避免在"匹配"结构中"使用可能未初始化的变量",这在Rust中未定义变量时是不可达的

Kon*_*lov 1 rust

我正在编写一个控制台Rust应用程序.它接受第一个参数并决定运行哪个模式.如果第一个参数未定义或未知,则应该退出应用程序.这是代码:

use std::env;
use std::process;

enum RunMode {
    Extract,
}

fn die_with_error(error: &str) {
    eprintln!("{}", &error);
    process::exit(-1);
}

fn main() {
    let mut args = env::args();
    args.next();
    let mut runmode;

    match args.next() {
        Some(arg) => {
            match arg.as_ref() {
                "extract" => runmode = RunMode::Extract,
                _ => die_with_error(&format!("Unknown mode {}", &arg.to_string())),
            };
        }
        None => die_with_error("No mode specified. Please specify a mode as a first argument. Use --help to get a list of modes available"),
    };

    match runmode {
        RunMode::Extract => {
            let file_name = args
                .next()
                .expect("Please specify a filename as a second argument");
            println!("You passed {}", file_name);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这不会编译并产生以下错误:

error[E0381]: use of possibly uninitialized variable: `runmode`
  --> src/main.rs:27:11
   |
27 |     match runmode {
   |           ^^^^^^^ use of possibly uninitialized `runmode`
Run Code Online (Sandbox Code Playgroud)

我知道有些情况下可以定义runmode,但在这些情况下,match将永远不会到达第27行.我可以通过为runmode定义默认值来避免,但这似乎并不干净.什么是在Rust中处理这个问题的正确方法?

Wes*_*ser 5

从编译器的角度来看,当您调用时die_with_error(),您的函数不会向调用者返回任何值.实际上,这个函数不仅没有返回任何内容,它根本不返回.在Rust中表达它的方法是使用never类型!:

fn die_with_error(error: &str) -> ! {
    eprintln!("{}", &error);
    process::exit(-1)
}
Run Code Online (Sandbox Code Playgroud)

通过此更改,编译器将知道runmode必须始终具有初始化值.