支持 Rust 1.0 的代码最直译是这样的:
use std::{fs, path::Path, ffi::OsStr};
fn getList(action_dir_path: &str) -> Vec<&OsStr> {
let v = fs::read_dir(&Path::new(action_dir_path))
.unwrap()
.map(|x| x.unwrap().path().file_stem().unwrap())
.collect();
return v;
}
这会产生错误消息:
铁锈 2015
error[E0597]: borrowed value does not live long enough
--> src/lib.rs:6:18
|
6 | .map(|x| x.unwrap().path().file_stem().unwrap())
| ^^^^^^^^^^^^^^^^^ - temporary value only lives until here
| |
| temporary value does not live long enough
|
note: borrowed value must be valid for the anonymous lifetime #1 defined on the function body at 3:1...
--> src/lib.rs:3:1
|
3 | / fn getList(action_dir_path: &str) -> Vec<&OsStr> {
4 | | let v = fs::read_dir(&Path::new(action_dir_path))
5 | | .unwrap()
6 | | .map(|x| x.unwrap().path().file_stem().unwrap())
7 | | .collect();
8 | | return v;
9 | | }
| |_^
铁锈 2018
error[E0515]: cannot return value referencing temporary value
--> src/lib.rs:6:18
|
6 | .map(|x| x.unwrap().path().file_stem().unwrap())
| -----------------^^^^^^^^^^^^^^^^^^^^^
| |
| returns a value referencing data owned by the current function
| temporary value created here
问题来自于Path::file_stem https://doc.rust-lang.org/std/path/struct.Path.html#method.file_stem。这是签名:
pub fn file_stem(&self) -> Option<&OsStr>
这表明该方法将返回一个借用参考OsStr
. The PathBuf
结构是owner字符串的。当你离开该方法时,就没有任何地方可以拥有该方法了PathBuf
,所以它会被丢弃。这意味着任何对PathBuf
将不再有效。这是 Rust 阻止您引用不再分配的内存,对 Rust 来说是的!
你能做的最简单的事情就是返回一个Vec<String>
. String
拥有其中的字符串,所以我们不需要担心当我们离开函数时它会被释放:
fn get_list(action_dir_path: &str) -> Vec<String> {
fs::read_dir(action_dir_path)
.unwrap()
.map(|x| {
x.unwrap()
.path()
.file_stem()
.unwrap()
.to_str()
.unwrap()
.to_string()
})
.collect()
}
我还更新了样式(免费!),使其更像 Rust:
- Use
snake_case
对于物品
- 类型定义中冒号前不能有空格
- 没有理由设置一个变量只是为了返回它。
- 不要使用显式的
return
语句,除非您提前退出函数。
- 无需将路径包装在
Path
.
然而,我并不喜欢所有的拆包。我会这样写这个函数:
use std::{ffi::OsString, fs, io, path::Path};
fn get_list(action_dir_path: impl AsRef<Path>) -> io::Result<Vec<OsString>> {
fs::read_dir(action_dir_path)?
.map(|entry| entry.map(|e| e.file_name()))
.collect()
}
fn main() {
println!("{:?}", get_list("/etc"));
}
除了上述更改外:
- 我使用通用类型作为输入路径。
- 我返回一个
Result
将错误传播给调用者。
- 我直接问
DirEntry
为文件名。
- 我将类型保留为
OsString
.