Rust循环中借用值生命周期不足问题求助
Redis PubSub到ZMQ重广播器的生命周期问题
我在实现Redis到ZMQ的重广播器时,卡在了循环中处理PubSub消息生成的临时值的生命周期问题上。我知道问题出在哪,但就是没法生成ZMQ发布者需要的Vec<&String>,试过改类型、克隆各种操作,还是一直碰到所有权和生命周期相关的错误。
问题代码
async fn ps_rebroadcaster() -> Result<(), ApiError>{ let mut inproc_publisher: async_zmq::Publish<std::vec::IntoIter<&std::string::String>, &std::string::String> = async_zmq::publish("ipc://pricing")?.bind()?; let con_str = &APP_CONFIG.REDIS_URL; let conn = create_client(con_str.to_string()) .await .expect("Can't connect to redis"); let mut pubsub = conn.get_async_connection().await?.into_pubsub(); match pubsub.psubscribe("T1050_*").await { Ok(_) => {} Err(_) => {} }; let mut msg_stream = pubsub.into_on_message(); loop { let result = msg_stream.next().await; match result { Some(message) => { let channel_name = message.get_channel_name().to_string(); let payload_value: redis::Value = message.get_payload().expect("Can't get payload of message"); let payload_string: String = FromRedisValue::from_redis_value(&payload_value).expect("Can't convert from Redis value"); let item: Vec<&String> = vec![&channel_name , &payload_string ]; // problem here ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ inproc_publisher.send(item.into()).await?; } None => { println!("None received"); continue; } } } }
错误信息
error[E0597]: `channel_name` does not live long enough --> src/server.rs:248:47 | 248 | let item: Vec<&String> = vec![&channel_name , &payload_string ]; | ^^^^^^^^^^^^^ borrowed value does not live long enough 249 | 250 | inproc_publisher.send(item.into()).await?; | ---------------------------------- borrow later used here 251 | } | - `channel_name` dropped here while still borrowed error[E0597]: `payload_string` does not live long enough --> src/server.rs:248:63 | 248 | let item: Vec<&String> = vec![&channel_name , &payload_string ]; | ^^^^^^^^^^^^^^^ borrowed value does not live long enough 249 | 250 | inproc_publisher.send(item.into()).await?; | ---------------------------------- borrow later used here 251 | } | - `payload_string` dropped here while still borrowed
问题根源
你定义的inproc_publisher类型要求接收引用类型的消息,但channel_name和payload_string都是循环块内的局部变量,生命周期只到当前循环迭代结束。ZMQ的send是异步操作,编译器无法保证这些引用在异步操作完成前还能存活,因此抛出生命周期错误。
解决方法
直接改用拥有所有权的String类型构造消息,避免引用带来的生命周期问题:
修改后的代码
async fn ps_rebroadcaster() -> Result<(), ApiError>{ // 调整发布者类型为接收String的迭代器 let mut inproc_publisher: async_zmq::Publish<std::vec::IntoIter<String>, String> = async_zmq::publish("ipc://pricing")?.bind()?; let con_str = &APP_CONFIG.REDIS_URL; let conn = create_client(con_str.to_string()) .await .expect("Can't connect to redis"); let mut pubsub = conn.get_async_connection().await?.into_pubsub(); // 不要忽略订阅错误,可添加日志或错误处理 if pubsub.psubscribe("T1050_*").await.is_err() { eprintln!("Failed to subscribe to T1050_* channels"); }; let mut msg_stream = pubsub.into_on_message(); loop { let result = msg_stream.next().await; match result { Some(message) => { let channel_name = message.get_channel_name().to_string(); let payload_value = message.get_payload().expect("Can't get payload of message"); let payload_string = FromRedisValue::from_redis_value(&payload_value) .expect("Can't convert from Redis value"); // 直接构造Vec<String>,无需借用 let item = vec![channel_name, payload_string]; inproc_publisher.send(item.into()).await?; } None => { println!("None received"); continue; } } } }
额外优化建议
- 不要忽略
psubscribe、get_payload等操作的错误,可将expect替换为?并在ApiError中添加对应的错误变体,实现统一错误处理 - 可添加日志记录关键步骤,方便后续排查问题
内容的提问来源于stack exchange,提问作者mike_t
相关产品推荐
相关产品推荐

