rust - 在 Rust 中,如何将具有生命周期的对象推送到向量中?

标签 rust lifetime borrow-checker lifetime-scoping

我有一些类似于下面的代码,它尝试从 websocket 中读取数据,将 JSON 结果解析为一个结构,然后将该结构推送到 Vec缓冲。然而,代码无法编译,因为结构有生命周期,并且借用检查器提示 JSON 字符串的生命周期不够长。

use serde::{Deserialize, Serialize};
use tungstenite::client::AutoStream;
use tungstenite::protocol::WebSocket;

#[derive(Serialize, Deserialize, Debug, Clone)]
struct MyType<'a> {
    id: &'a str,
    count: i64,
}

fn example<'a>(
    conn: &mut WebSocket<AutoStream>,
    buff: &'a mut Vec<MyType<'a>>,
) -> Option<Box<dyn std::error::Error>> {
    match conn.read_message() {
        Err(err) => Some(err.into()),
        Ok(msg) => {
            let resp_raw = msg.to_string();
            let resp_parsed: Result<MyType<'a>, _> = serde_json::from_str(&resp_raw);
            match resp_parsed {
                Err(err) => Some(err.into()),
                Ok(resp) => {
                    buff.push(resp.clone());
                    None
                }
            }
        }
    }
}

确切的错误是 borrowed value [&resp_raw] does not live long enough .

我想知道我应该如何重构这段代码以满足借用检查器;将具有生命周期的结构推送到 Vec 的正确方法是什么?参数?

还是 &'a str解析为 MyType实际上仍然保留对原始 JSON 字符串的引用,所以没有办法安全地做到这一点?

最佳答案

serde_json::from_str小心:

pub fn from_str<'a, T>(s: &'a str) -> Result<T> 
where
    T: Deserialize<'a>, 

这表示 T反序列化与输入 s 共享相同的生命周期.这允许零拷贝反序列化,这就是你在 MyType 中得到的。 , 其中 id是对字符串切片的引用。这将绑定(bind) MyType 的生命周期到 &resp_raw 的生命周期,这是 fn example() 的本地.这行不通。

buff不能解决问题你给它的生命周期参数。 example -function 拥有 MyType 的缓冲区指向。允许MyType “逃”到Vec将允许创建悬空引用,因为缓冲区被销毁一次 example返回。

更改MyType满足DeserializeOwned ,即不带生命周期参数。你需要一个 String或者一个(为了安全起见)一个Box<str>而不是 &str .

关于rust - 在 Rust 中,如何将具有生命周期的对象推送到向量中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59116374/

相关文章:

methods - 如何在 HashMap 中存储方法指针并调用它们

rust - 在 Rust 中,如何在格式中使用变量!宏?

rust - FnOnce 的泛型,返回一个终生的 future

rust - 为什么不能在同一结构中存储值和对该值的引用?

templates - 如何为泛型使用括号?

rust - 什么时候静态生命周期不合适?

python - 如何实现rust-cpython as_object()和into_object()?

rust - 如何使用枚举作为数组元素?

rust - 处理由 C FFI 强制执行的有问题的父子关系

rust - 从 HashMap 或 Vec 返回引用会导致借用超出其所在范围?