Rust编译错误E0597:borrowed value does not live long enough解决方案咨询
Rust生命周期错误:
timestamp生命周期不足的解决方案 问题背景
代码示例
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(&timestamp, 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(&timestamp, 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分支内的解决方案。
解答
一、为什么n没有生命周期问题?
n是Duration类型,as_secs()方法返回的是Copy类型u64。调用该方法时,会把n中的秒数复制一份存入HashMap,而非借用n的值。n虽在Ok分支结束后被销毁,但HashMap里存的是独立的u64副本,和n的生命周期无关,因此编译器不会报错。
而timestamp是String类型,你存入HashMap的是它的引用&String,这个引用的生命周期必须与HashMap一致,但timestamp在Ok分支结束时就被销毁,导致HashMap持有悬垂引用,这就是编译器报错的核心原因。
二、保留timestamp在Ok分支内的解决方案
1. 让HashMap持有String所有权(推荐)
直接修改HashMap类型为HashMap<String, u64>,将timestamp的所有权转移给HashMap,无需借用:
use std::time::SystemTime; use std::collections::HashMap; use serde_json; fn main() { let mut payload = HashMap::new(); // 编译器自动推导为HashMap<String, u64> match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) { Ok(n) => { let timestamp = "timestamp".to_string(); payload.insert(timestamp, n.as_secs()); // 转移所有权,避免生命周期问题 } Err(_) => panic!("SystemTime before UNIX EPOCH!"), }; println!("{}", serde_json::to_string(&payload).unwrap()) }
2. 使用静态字符串切片
如果键是固定的静态字符串,直接使用&'static str类型的字面量,它的生命周期覆盖整个程序运行期,不会被销毁:
use std::time::SystemTime; use std::collections::HashMap; use serde_json; fn main() { let mut payload = HashMap::new(); // 编译器自动推导为HashMap<&'static str, u64> match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) { Ok(n) => { payload.insert("timestamp", n.as_secs()); // 直接使用静态字符串 } Err(_) => panic!("SystemTime before UNIX EPOCH!"), }; println!("{}", serde_json::to_string(&payload).unwrap()) }
内容的提问来源于stack exchange,提问作者DobbyTheElf
相关产品推荐
相关产品推荐

