从匹配语句赋值

  • 本文关键字:赋值 语句 rust
  • 更新时间 :
  • 英文 :


我正在尝试在 Rust 中制作一个 Git 命令。我正在使用clap参数解析器箱来执行命令行处理。我希望我的命令采用一个可选参数来执行哪个目录的工作。如果命令未收到该选项,则假定用户主目录。

我知道如果设置了 std::env::home_dir 函数,我可以使用 函数来获取用户的主目录,但让我感到困惑的部分是如何正确使用 match 运算符来获取路径的值。这是我一直在尝试的:

use std::env;
fn main() {
    // Do some argument parsing stuff...
    let some_dir = if matches.is_present("some_dir") {
        matches.value_of("some_dir").unwrap()
    } else {
        match env::home_dir() {
            Some(path) => path.to_str(),
            None       => panic!("Uh, oh!"),
        }
    };
    // Do more things

当我尝试编译此消息时,我收到一条错误消息,说path.to_str()寿命不够长。我知道从to_str返回的值在match作用域的长度上存在,但是如何从必须调用另一个函数的匹配语句中返回值?

path.to_str()将返回对包含在path中的内部字符串的&str引用,该字符串只会在match臂内path存在。您可以使用to_owned获取该&str的拥有副本。您必须相应地调整 clap 中的值,以便在以下情况下的两个分支中具有相同的类型:

let some_dir = if matches.is_present("some_dir") {
    matches.value_of("some_dir").unwrap().to_owned()
} else {
    match env::home_dir() {
        Some(path) => path.to_str().unwrap().to_owned(),
        None       => panic!("Uh, oh!"),
    }
};

或者,您可以使用Cow来避免第一个分支中的复制:

use std::borrow::Cow;
let some_dir: Cow<str> = if matches.is_present("some_dir") {
    matches.value_of("some_dir").unwrap().into()
} else {
    match env::home_dir() {
        Some(path) => path.to_str().unwrap().to_owned().into(),
        None       => panic!("Uh, oh!"),
    }
};

正在发生的事情是 match 语句的作用域拥有从 env::home_dir() 返回的PathBuf对象的所有权。然后尝试返回对该对象的引用,但该对象立即不复存在。

解决方案是返回PathBuf而不是对它的引用(或将其转换为 String 并返回它,无论如何,它必须是拥有数据的某种类型(。您可能需要更改matches.value_of("some_dir").unwrap()返回的内容,以便两个分支返回相同的类型。

有一个相当简单的技巧:增加path的范围(从而增加它的生存期(,以便你可以引用它。

use std::env;
fn main() {
    // Do some argument parsing stuff...
    let path; // <--
    let some_dir = if matches.is_present("some_dir") {
        matches.value_of("some_dir").unwrap()
    } else {
        match env::home_dir() {
            Some(p)    => { path = p; path.to_str().unwrap() },
            None       => panic!("Uh, oh!"),
        }
    };
    // Do more things
}

它非常高效,因为path只在必要时使用,并且不需要更改程序中的类型。

注意:我在.to_str()后添加了一个.unwrap(),因为.to_str()返回一个Option。请注意,它返回Option<&str>的原因是并非所有路径都是有效的 UTF-8 序列。你可能想坚持 Path/PathBuf .

最新更新