简体   繁体   English

如何在 Rust 中按值返回结构?

[英]How to return a struct by value in Rust?

I'm learning Rust and failed on the first steps already... I have the next function:我正在学习 Rust 并且第一步已经失败了......我有下一个 function:

use std::env;
use std::path::Path;

fn get_path() -> Path {
    let args: Vec<String> = env::args().collect();
    assert!(!args.is_empty(), "Target path is required!");
    let path = Path::new(&args[0]);
    assert!(path.exists(), "Target path doesn't exist!");
    assert!(path.is_dir(), "Target path is not a directory!");
    return path;
}

It's very simple function but path is a reference and I can't get how can I return Path object from function by value?这是非常简单的 function 但path是一个参考,我不知道如何从 function 按值返回Path object? Or how to return a reference that will be alive in outer function context?或者如何返回将在外部 function 上下文中存在的引用?

PS I looked for similar question but I didn't get it, unfortunately. PS我寻找了类似的问题,但不幸的是我没有得到它。

Strictly speaking, Path is not a reference, it is rather an unsized type which can only exist behind a reference, and indeed Path::new returns &Path not Path .严格来说, Path不是一个引用,它是一个大小不一的类型,只能存在于引用后面,实际上Path::new返回&Path而不是Path Which is therefore incompatible with the -> Path you've annotated your function with.因此,这与您注释 function 的-> Path不兼容。

These are in fact the two things the compile error tells you, and you really want to give people compilation errors (or reproduction cases) when posting Rust code as the errors are extremely informative once you've gotten used to them:这些实际上是编译错误告诉您的两件事,并且您真的想在发布 Rust 代码时给人们编译错误(或再现案例),因为一旦您习惯了这些错误,它们就会提供非常丰富的信息:

error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
 --> src/lib.rs:4:18
  |
4 | fn get_path() -> Path {
  |                  ^^^^ borrow the `Path` instead
  |

says that you're returning an unsized type which is not allowed), and表示您返回的是不允许的未调整大小的类型),并且

error[E0308]: mismatched types
  --> src/lib.rs:10:12
   |
4  | fn get_path() -> Path {
   |                  ---- expected `std::path::Path` because of return type
...
10 |     return path;
   |            ^^^^ expected struct `std::path::Path`, found `&std::path::Path`

explains that the type you want to return doesn't match the type of the value you're returning.说明您要返回的类型与您要返回的值的类型不匹配。

Anyway as the official documentation for Path notes , the owned / structure version of Path is PathBuf , so you should return that, and convert your Path into a PathBuf , or really just create a PathBuf in the first place, eg无论如何,作为Path notes 的官方文档, Path Path拥有/结构版本是PathBuf ,因此您应该返回它,并将您的Path转换为PathBuf ,或者实际上只是首先创建一个PathBuf ,例如

use std::env;
use std::path::PathBuf;

fn get_path() -> PathBuf {
    let args: Vec<String> = env::args().collect();
    assert!(!args.is_empty(), "Target path is required!");
    let path = PathBuf::from(&args[0]);
    assert!(path.exists(), "Target path doesn't exist!");
    assert!(path.is_dir(), "Target path is not a directory!");
    path
}

Incidentally,顺便,

 Path::new(&args[0]);

is probably not what you expect or want: as the documentation for std::env::args notes:可能不是您期望或想要的:作为std::env::args的文档说明:

The first element is traditionally the path of the executable第一个元素通常是可执行文件的路径

and this is not an area where Rust has seen fit to diverge from the underlying system.这不是 Rust 认为适合偏离底层系统的领域。

You likely want args[1] instead, or to use a higher-level args-parsing API.您可能需要args[1] ,或者使用更高级别的 args 解析 API。

And an other aside related to Sven Marnach's comment to your question: calling path.exists then path.is_dir requires fetching the metadata twice (I don't think Rust caches this information).还有一个与 Sven Marnach 对您的问题的评论有关的另一边:调用path.exists然后path.is_dir需要两次获取元数据(我认为 Rust 不会缓存此信息)。 The efficienty aspect is probably not primordial here but you may still want to explicitly use Path::metadata , followed by asking that if is_dir ( Path::metadata will return an Err if the path is not to a valid on-disk thing).效率方面在这里可能不是原始的,但您可能仍想显式使用Path::metadata ,然后询问 if is_dir (如果路径不是有效的磁盘上的东西 Path::metadata将返回Err )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM