我有以下代码:
use std::time::SystemTime;
use std::collections::HashMap;
use serde_json;
fn main()
{
let mut payload = HashMap::<&String, u64>::new();
match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) {
Ok(n) => {
let timestamp = "timestamp".to_string();
payload.insert(×tamp, n.as_secs());
}
Err(_) => panic!("SystemTime before UNIX EPOCH!"),
};
println!("{}", serde_json::to_string(&payload).unwrap())
}
字符串
编译器会在以下情况下福尔斯:
error[E0597]: `timestamp` does not live long enough
--> src/main.rs:11:28
|
10 | let timestamp = "timestamp".to_string();
| --------- binding `timestamp` declared here
11 | payload.insert(×tamp, n.as_secs());
| ^^^^^^^^^^ borrowed value does not live long enough
12 | }
| - `timestamp` dropped here while still borrowed
...
15 | println!("{}", serde_json::to_string(&payload).unwrap())
| -------- borrow later used here
型
我可以通过将let timestamp = "timestamp".to_string();
移到match
之上来解决这个问题,但我不禁觉得还有更好的解决方案,而且我确实不明白为什么编译器没有对n
提出同样的抱怨。
有没有一个解决方案,包括将timestamp
的定义保留在Ok
子句中?
2条答案
按热度按时间6psbrbz91#
这里最大的问题是这两行:
字符串
这就是所谓的 * 对时态变量的引用 *。由于
HashMap
中的键是&String
引用,因此键的实际数据并不存储在HashMap
中。他们必须住在某个地方。在您的代码中,键的实际数据所在的位置是
timestamp
变量。但是在insert()
ing之后,您离开了timestamp
变量所在的作用域,它被销毁了;但是payload
中的条目仍然存在,并且该键成为悬空引用。编译器不允许这样做,因此出现错误。有两种方法可以解决此问题:
HashMap
中,方法是将密钥设置为String
payload
对象将密钥存储在
HashMap
中这可能看起来像这样:
的数据
确保密钥的寿命比
HashMap
长第二个例子有效的原因是,如果你不对字符串调用
to_string()
,它将是一个存储在全局常量内存中的&'static str
,并且永远存在。请注意,这个版本现在不再与
String
s兼容,它只能存储&str
引用,这些引用的寿命肯定超过payload
对象。使用String
s作为键有点浪费,但比使用&str
灵活得多。tf7tbtn22#
n
不是借来的。timestamp
被借用,并且借用放入容器中,然后timestamp
超出范围(这使容器无效)。一个装思想的容器而不是借来的怎么样。例如
let mut payload = HashMap::<String, u64>::new();
。你将不得不修复另一个借用时间戳的地方。我把这个留给你。