我正在尝试在 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
.