解析Rust?struct?中的生命周期
最近在用rust 寫一個redis的數據校驗工具。redis-rs中具備 redis::ConnectionLike trait,借助它可以較好的來抽象校驗過程。在開發(fā)中,不免要定義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 的生命周期保證了內存的安全性,同時也增加了開發(fā)者的心智負擔。是在上線之前多費心思寫代碼,還是在上線以后忙忙活活查問題,這是個 trade off 問題。俗話講:"背著抱著,一樣沉".我本人還是傾向于把問題控制在上線之前,少折騰用戶。
到此這篇關于Rust struct 中的生命周期的文章就介紹到這了,更多相關Rust struct生命周期內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
為什么要使用 Rust 語言、Rust 語言有什么優(yōu)勢
雖然 Rust 是一種通用的多范式語言,但它的目標是 C 和 C++占主導地位的系統(tǒng)編程領域,很多朋友會問rust語言難學嗎?rust語言可以做什么,今天帶著這些疑問通過本文詳細介紹下,感興趣的朋友一起看看吧2022-10-10