返回引用、静态引用和值时出错

Error while returning reference, static reference and value

use std::path::Path;
use std::path::PathBuf;

struct Deploy(PathBuf);

impl Deploy {
    fn values_yaml(self) -> Path {
        let values_yaml = self.0.join("helm").join("chart").join("values.yaml");
        values_yaml
    }
}

这是我的功能,
当 return 类型是 &Path 我得到 expected named lifetime parameter.
当 return 类型是 &static Path 我得到 returns a reference to data owned by the current function.
当 return 类型 Path 我得到 doesn't have a size known at compile-time.

如何才能使该功能发挥作用?

这里的问题是 Path 类型是引用类型。它基本上指向现有的拥有 PathBuf.

这是一个等价于 strString 的关系。

此外,Path::join() 方法 return 是 PathBuf(参见 https://doc.rust-lang.org/stable/std/path/struct.Path.html#method.join)。

此处的解决方案是相应地更改您的 return 类型:

use std::path::Path;
use std::path::PathBuf;

struct Deploy(PathBuf);

impl Deploy {
    fn values_yaml(self) -> PathBuf {
        let values_yaml = self.0.join("helm").join("chart").join("values.yaml");
        values_yaml
    }
}

Playground link

Path 是一个未定大小的类型,这意味着它必须始终在像 &Box 这样的指针后面使用。该类型的拥有版本为 PathBufPathBuf 实现了 DerefPath,因此您可以使用它的所有方法。这就解释了为什么你不能 return Path.
现在为什么你不能 return &Path 从你的方法?看看 joinCreates an owned PathBuf with path adjoined to self。所以你在你的方法中创建了一个新的 PathBuf 和 return 对它的引用。但是一旦方法结束并且 PathBuf 超出范围,这个新的将被删除。您目前还取得了 self 的所有权,因此即使您不创建新的而只是推送到它,这也会删除 PathBuf

那么解决方案会是什么样子呢?假设您不想修改 Deploy 中的 PathBuf,您只需 return 一个拥有的 PathBuf.

use std::path::Path;
use std::path::PathBuf;

struct Deploy(PathBuf);

impl Deploy {
    fn values_yaml(&self) -> PathBuf {
        self.0.join("helm").join("chart").join("values.yaml")
    }
}

fn main() {
    let s = r"/etc";
    let deploy = Deploy(PathBuf::from(s));
    let values_yaml = deploy.values_yaml();
    i_take_a_path(&values_yaml);
}

fn i_take_a_path(path: &Path) {
    println!("{:?}", path);
}

如果你真的想修改 Deploy 的基础 PathBuf,你会这样做:

use std::path::Path;
use std::path::PathBuf;

struct Deploy(PathBuf);

impl Deploy {
    fn values_yaml(&mut self) -> &Path {
        self.0.push("helm");
        self.0.push("chart");
        self.0.push("values.yaml");
        self.0.as_path()
    }
}

fn main() {
    let s = r"/etc";
    let mut deploy = Deploy(PathBuf::from(s));
    let values_yaml = deploy.values_yaml();
    i_take_a_path(values_yaml);
}

fn i_take_a_path(path: &Path) {
    println!("{:?}", path);
}

这次引用有效,因为它直接指向 Deploy 中的 PathBuf,而不是新创建的。