Rust生命周期错误排查:borrowed value does not live long enough问题解决
解决Rust中
borrowed value does not live long enough生命周期错误 这个问题的核心矛盾很明确:你调用的get_user_guild_nick函数要求传入的fields参数是Vec<&'static str>——也就是生命周期为整个程序运行期间的字符串引用,但你从lists生成的&str引用,生命周期只局限于json_to函数内部,自然无法满足'static的要求。
而注释里用字面量生成的Vec<String>能正常运行,是因为字符串字面量本身就属于'static生命周期,它们的引用自然也符合&'static str的要求。
下面是几种可行的解决方案,按推荐程度排序:
方案1:修改get_user_guild_nick的参数类型(最优解)
&'static str的限制过于严格,完全没有必要——你并不需要这些字符串存活到程序结束,只要在函数调用期间有效就行。我们可以调整函数的生命周期约束,或者直接改用String来传递所有权:
方式A:使用带生命周期的切片参数
把函数参数从Vec<&'static str>改成带生命周期的&[&str],同时调整返回值的HashMap键类型:
use std::collections::HashMap; use redis::AsyncCommands; pub async fn get_user_guild_nick<'a>( &self, user_id: String, fields: &'a [&'a str], ) -> Result<HashMap<&'a str, Option<String>>, redis::RedisError> { let mut _con = self.connect.clone(); let key = KEYMAP["user_nick"].replace("%s1", &user_id); let result: Vec<Option<String>> = cmd("hmget") .arg(key) .arg(fields) .query_async(&mut _con) .await .unwrap_or(vec![None]); let mut map: HashMap<&'a str, Option<String>> = HashMap::new(); for (idx, field) in fields.iter().enumerate() { map.insert(field, result[idx].clone()); } Ok(map) }
修改后,在json_to里直接传递lists的引用切片即可,不需要额外转换:
let field_refs: Vec<&str> = lists.iter().map(|s| s.as_str()).collect(); let my_nicks = redis_handle .get_user_guild_nick(info.u_id.clone().to_string(), &field_refs) .await .unwrap();
方式B:改用Vec<String>传递所有权
如果不想处理生命周期,直接让函数接收Vec<String>,同时把返回值的HashMap键改成String(这样所有权完全可控):
use std::collections::HashMap; use redis::AsyncCommands; pub async fn get_user_guild_nick( &self, user_id: String, fields: Vec<String>, ) -> Result<HashMap<String, Option<String>>, redis::RedisError> { let mut _con = self.connect.clone(); let key = KEYMAP["user_nick"].replace("%s1", &user_id); // 把String转成&str传给redis命令 let field_refs: Vec<&str> = fields.iter().map(|s| s.as_str()).collect(); let result: Vec<Option<String>> = cmd("hmget") .arg(key) .arg(&field_refs) .query_async(&mut _con) .await .unwrap_or(vec![None]); let mut map: HashMap<String, Option<String>> = HashMap::new(); for (idx, field) in fields.into_iter().enumerate() { map.insert(field, result[idx].clone()); } Ok(map) }
这种情况下,json_to里直接传lists就行,不需要任何转换:
let my_nicks = redis_handle .get_user_guild_nick(info.u_id.clone().to_string(), lists) .await .unwrap();
方案2:在不修改函数的前提下强制生成&'static str(不推荐)
如果因为某些原因无法修改get_user_guild_nick,可以通过内存泄漏的方式把String转换成&'static str——但这会导致这些字符串永远不会被释放,只有在确定这些字符串数量极少且不会频繁创建时才考虑使用:
let v8: Vec<&'static str> = lists.into_iter() .map(|s| Box::leak(s.into_boxed_str())) .collect(); let my_nicks = redis_handle .get_user_guild_nick(info.u_id.clone().to_string(), v8) .await .unwrap();
内容的提问来源于stack exchange,提问作者dragon C
相关产品推荐
相关产品推荐

