写点什么

文盘 Rust -- struct 中的生命周期

  • 2022 年 10 月 08 日
    北京
  • 本文字数:1702 字

    阅读完需:约 6 分钟

文盘Rust -- struct 中的生命周期

最近在用 rust 写一个 redis 的数据校验工具。redis-rs中具备 redis::ConnectionLike trait,借助它可以较好的来抽象校验过程。在开发中,不免要定义 struct 中的某些元素为 trait object,从而带来一些 rust 语言中的生命周期问题。本文不具体讨论 redis 的数据校验过程,通过一个简单的例子来聊聊 struct 中 trait object 元素的生命周期问题。


首先来定义一个 base trait,该 trait 中只包含一个函数,返回 String 类型。


pub trait Base {    fn say(&self) -> String;}
复制代码


接下来,定义两个实现了 Base trait 的 struct AFromBase 和 BFromBase


pub struct AFromBase {    content: String,}
impl Base for AFromBase { fn say(&self) -> String { self.content.clone() }}
pub struct BFromBase { text: String,}
impl Base for BFromBase { fn say(&self) -> String { self.text.clone() }}
复制代码


接下来,定义一个 struct 包含两个 Base trait 的 trait object ,然后实现一个函数是 say 函数输出的字符串的拼接结果.按照其他没有生命周期语言的编写习惯,直觉上这么写


pub struct AddTowBase {    a: &mut dyn Base,    b: &mut dyn Base,}
impl AddTowBase { fn add(&self) -> String { let result = self.a.say() + &self.b.say(); result }}
复制代码


最后,搞个 main 函数验证一下。完整代码如下


pub trait Base {    fn say(&self) -> String;}
pub struct AFromBase { content: String,}
impl Base for AFromBase { fn say(&self) -> String { self.content.clone() }}
pub struct BFromBase { text: String,}
impl Base for BFromBase { fn say(&self) -> String { self.text.clone() }}
pub struct AddTowBase { a: &mut dyn Base, b: &mut dyn Base,}
impl<'a> AddTowBase<'a> { fn add(&self) -> String { let result = self.a.say() + &self.b.say(); result }}
fn main() { let mut a = AFromBase { content: "baseA".to_string(), };
let mut b = BFromBase { text: "baseB".to_string(), };
let addtow = AddTowBase { a: &mut a, b: &mut b, }; let r = addtow.add(); println!("{}", r);}
复制代码


很遗憾,以上代码是不能编译通过的,编译时报如下错误


error[E0106]: missing lifetime specifier  --> examples/lifetimeinstruct.rs:26:8   |26 |     a: &mut dyn Base,   |        ^ expected named lifetime parameter   |help: consider introducing a named lifetime parameter   |25 ~ pub struct AddTowBase<'a> {26 ~     a: &'a mut dyn Base,   |
error[E0106]: missing lifetime specifier --> examples/lifetimeinstruct.rs:27:8 |27 | b: &mut dyn Base, | ^ expected named lifetime parameter |help: consider introducing a named lifetime parameter |25 ~ pub struct AddTowBase<'a> {26 | a: &mut dyn Base,27 ~ b: &'a mut dyn Base, |
For more information about this error, try `rustc --explain E0106`.error: could not compile `wenpan-rust` due to 2 previous errors
复制代码


编译器给出的提示很明确,要在 trait object 上添加生命周期参数,确保 struct 和他的 trait object 元素在同一生命周期,避免悬垂指针。我们按照编译器的提示修改代码


pub struct AddTowBase<'a> {    a: &'a mut dyn Base,    b: &'a mut dyn Base,}
impl<'a> AddTowBase<'a> { fn add(self) -> String { let result = self.a.say() + &self.b.say(); result }}
复制代码


代码顺利通过编译。rust 的生命周期保证了内存的安全性,同时也增加了开发者的心智负担。是在上线之前多费心思写代码,还是在上线以后忙忙活活查问题,这是个 trade off 问题。俗话讲:"背着抱着,一样沉".我本人还是倾向于把问题控制在上线之前,少折腾用户。


本期咱们先聊到这儿,下期见


发布于: 刚刚阅读数: 3
用户头像

拥抱技术,与开发者携手创造未来! 2018.11.20 加入

我们将持续为人工智能、大数据、云计算、物联网等相关领域的开发者,提供技术干货、行业技术内容、技术落地实践等文章内容。京东云开发者社区官方网站【https://developer.jdcloud.com/】,欢迎大家来玩

评论

发布
暂无评论
文盘Rust -- struct 中的生命周期_redis_京东科技开发者_InfoQ写作社区