日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學(xué)無先后,達(dá)者為師

網(wǎng)站首頁 編程語言 正文

解析Rust?struct?中的生命周期_Rust語言

作者:京東云開發(fā)者 ? 更新時(shí)間: 2022-11-21 編程語言

最近在用rust 寫一個redis的數(shù)據(jù)校驗(yàn)工具。redis-rs中具備 redis::ConnectionLike trait,借助它可以較好的來抽象校驗(yàn)過程。在開發(fā)中,不免要定義struct 中的某些元素為 trait object,從而帶來一些rust語言中的生命周期問題。
本文不具體討論 redis的數(shù)據(jù)校驗(yàn)過程,通過一個簡單的例子來聊聊 struct 中 trait object 元素的生命周期問題。

首先來定義一個 base trait,該 trait 中只包含一個函數(shù),返回String類型。

pub trait Base {
    fn say(&self) -> String;
}

接下來,定義兩個實(shí)現(xiàn)了 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 ,然后實(shí)現(xiàn)一個函數(shù)是 say 函數(shù)輸出的字符串的拼接結(jié)果.
按照其他沒有生命周期語言的編寫習(xí)慣,直覺上這么寫

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函數(shù)驗(yàn)證一下。
完整代碼如下

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);
}

很遺憾,以上代碼是不能編譯通過的,編譯時(shí)報(bào)如下錯誤

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 上添加生命周期參數(shù),確保 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 的生命周期保證了內(nèi)存的安全性,同時(shí)也增加了開發(fā)者的心智負(fù)擔(dān)。是在上線之前多費(fèi)心思寫代碼,還是在上線以后忙忙活活查問題,這是個 trade off 問題。俗話講:"背著抱著,一樣沉".我本人還是傾向于把問題控制在上線之前,少折騰用戶。

原文鏈接:https://www.cnblogs.com/Jcloud/p/16768365.html

欄目分類
最近更新