最近在用rust 写一个redis的数据校验工具。[redis-rs](https://github.com/redis-rs/redis-rs)中具备 redis::ConnectionLike trait,借助它可以较好的来抽象校验过程。在开发中,不免要定义struct 中的某些元素为 trait object,从而带来一些rust语言中的生命周期问题。
首先来定义一个 base trait,该 trait 中只包含一个函数,返回String类型。
```rustpub trait Base {fn say(&self) -> String;}```
```Rustpub 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()}}```
按照其他没有生命周期语言的编写习惯,直觉上这么写
```rustpub 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函数验证一下。
完整代码如下:
```rustpub 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);}```
很遗憾,以上代码是不能编译通过的,编译时报如下错误:
```shellerror[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```
我们按照编译器的提示修改代码:
```rustpub 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 问题。俗话讲:"背着抱着,一样沉"。我本人还是倾向于把问题控制在上线之前,少折腾用户。
本期咱们先聊到这儿,下期见。

