Rust 格式的生命周期!()中的匹配表达式太短

Rust 格式的生命周期!()中的匹配表达式太短,rust,Rust,我正在为自己的结构实现一个自定义的Display::fmt,它表示一个间隔 struct Range<T> { lower: Option<T>, upper: Option<T>, } 我已开始实现,但在匹配表达式和格式生成的字符串的生存期方面遇到了问题!()。我的实现存在的问题是,格式返回的字符串没有足够长的使用时间 fn main() { let opt = Some(1); let opt_display = mat

我正在为自己的结构实现一个自定义的
Display::fmt
,它表示一个间隔

struct Range<T> {
    lower: Option<T>,
    upper: Option<T>,
}
我已开始实现,但在
匹配
表达式和
格式生成的字符串的生存期方面遇到了问题!()
。我的实现存在的问题是,格式返回的字符串没有足够长的使用时间

fn main() {
    let opt = Some(1);

    let opt_display = match opt {
        Some(x) => &format!("{}", x), // error: borrowed value does not live long enough
        None => "",
    };

    println!("opt: {}", opt_display);
}

为什么我的方法不起作用?什么是解决我问题的好方法?

我不是生命周期方面的专家,但我相信这里的问题是,您试图从
格式创建的
字符串中返回
&String
在匹配中。由于格式的范围仅在范围内,借阅检查器会投诉

要解决此问题,可以使用一个自有字符串

fn main() {
    let opt = Some(1);

    let opt_display = match opt {
        Some(ref x) => format!("{}", x), // Allowed since opt_display now owns the string
        None => "".into(),
    };
    // Another way to achieve the same thing.
    //let opt_display = opt.map(|s| format!("{}", s)).unwrap_or("".into());

    println!("opt: {}", opt_display);
}
因为,您正试图返回对某个值的引用,该值将在引用仍然存在时被删除。祝贺你,你只是试图创建内存不安全,这可能导致C或C++中的崩溃(或者更糟),但是锈阻止了它。p> 您可以提高效率的一个方法是仅在一种情况下分配:

fn main() {
    let opt = Some(1);
    let opt_display = opt.map(|s| format!("{}", s));

    // Type not needed, only used to assert the type is what we expect
    let opt_display_str: &str = opt_display.as_ref().map(String::as_str).unwrap_or("");
    println!("opt: {}", opt_display_str);
}
您还可以使用,它允许拥有或借用字符串。注意它与另一个答案有多相似,但在
None
的情况下不分配:

use std::borrow::Cow;

fn main() {
    let opt = Some(1);

    let opt_display: Cow<str> = match opt {
        Some(ref x) => format!("{}", x).into(),
        None => "".into(),
    };

    println!("opt: {}", opt_display);
}

替换
write!(f,
用于
打印!(
在格式化程序中,并在出错时返回。

在实现
显示时,无需返回字符串;您只需
将!()
写入提供的格式化程序即可

它看起来像:

impl<T: Display> Display for Range<T> {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), std::fmt::Error> {
        write!(fmt, "<")?;
        if let Some(v) = self.lower {
            write!(fmt, "{}", v)?;
        }
        write!(fmt, ",")?;
        if let Some(v) = self.upper {
            write!(fmt, "{}", v)?;
        }
        write!(fmt, ">")
    }
}
impl范围显示{
fn fmt(&self,fmt:&mut格式化程序)->结果{
写!(fmt,“”)
}
}

if let Some(ref x)=
解决方案正是我想要的。我现在明白了为什么我以前的代码不起作用了。在Rust中工作肯定会让人大开眼界。感谢您的详细介绍。在进行多个
编写时!(
按顺序,每个似乎都返回某种结果。编译器显示
警告:必须使用未使用的结果,
。我当前使用
#[允许(未使用的#必须使用)]忽略该警告
。有没有办法
写入!
fmt::Formatter
上可能会失败?这是一种不好的做法吗?@antenen是的,并且?使用
结果
,就像生锈的其他地方一样,可能是“出错时返回”,就像我提到的那样。也许重新使用Rust编程语言会有所帮助?另请参见。@Antenen有没有办法在
fmt::Formatter
写入!
可能会失败?-当然。磁盘可能已满,文件可能已关闭,网络可能已断开…等等。这是一种不好的做法吗?忽略错误?绝对正确这是个坏主意,这就是为什么编译器告诉您应该使用
结果的原因。我还没有阅读错误处理一章。我昨天通过阅读“这本书”开始学习生锈.非常有趣的语言。我将研究它!感谢您提供的精彩答案。我选择接受Shepmaster的答案,因为它描述了我的解决方案为什么不能最好地工作,并为我的问题提供了多种解决方案。
fn main() {
    let opt = Some(1);

    print!("opt: ");

    if let Some(ref x) = opt  {
       print!("{}", x);
    }

    println!("");    
}
impl<T: Display> Display for Range<T> {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), std::fmt::Error> {
        write!(fmt, "<")?;
        if let Some(v) = self.lower {
            write!(fmt, "{}", v)?;
        }
        write!(fmt, ",")?;
        if let Some(v) = self.upper {
            write!(fmt, "{}", v)?;
        }
        write!(fmt, ">")
    }
}