我的第一篇rust博客

接触rust是在一个前端的群里,群主推荐的。混群很久都没有引起我的注意,直到有一次百度了解,才发现它的魅力。而且它是WebAssembly首推的编程语言,自然有它的独特之处。
rust标榜内存安全和线程安全,并且并不是虚拟机语言,不存在垃圾回收。基本上就是可以兼顾虚拟机语言的自由和非虚拟机语言的速度,当然有得有失,带来的缺点就是语法丑陋,难以掌握,这对于它带来的好处来说都不是事儿。
rust的内存安全和线程安全实现机制就是独占内存资源的所有权,任何时候只允许只有一个变量(可以是变量的引用)对内存进行修改,并且引用是有生命周期的,编译器会约束引用的使用,它在原始变量释放内存之前必须归还,以杜绝垂悬指针,不按规则使用,就会编译不通过。
第一篇rust博客就是关于引用生命周期的,直接贴一段错误代码,从数据库操作中分离出来的。

 1 struct Person {
 2     pub name: String,
 3     pub addr: String
 4 }
 5 fn addVal<'a>(vals: &'a mut Vec<&'a str>, person: &'a Person) {
 6     vals.push(&person.name);
 7     vals.push(&person.addr);
 8 }
 9 fn print(vals: &[&str]) {
10 }
11 fn main() {
12     let person = Person {
13         name: String::from("name"),
14         addr: String::from("addr")
15     };
16     let mut vals: Vec<&str> = Vec::new();
17     addVal(&mut vals, &person);
18     print(&vals);
19 }

按此代码编译不通过,编译报错如下:

   Compiling train v0.1.0 (E:codegit	rain)
warning: unused variable: `vals`
 --> srcmain.rs:9:10
  |
9 | fn print(vals: &[&str]) {
  |          ^^^^ help: consider prefixing with an underscore: `_vals`
  |
  = note: `#[warn(unused_variables)]` on by default

error[E0502]: cannot borrow `vals` as immutable because it is also borrowed as mutable
  --> srcmain.rs:18:11
   |
17 |     addVal(&mut vals, &person);
   |            --------- mutable borrow occurs here
18 |     print(&vals);
   |           ^^^^^
   |           |
   |           immutable borrow occurs here
   |           mutable borrow later used here

error: aborting due to previous error

For more information about this error, try `rustc --explain E0502`.
error: could not compile `train`.

To learn more, run the command again with --verbose.

此处报错addVal调用的时候借用了一个可变引用,之后的print方法又借用了一个共享引用,但是并不是同时借用的,一先一后,按常理,addVal处的借用应该在调用之后就归还所有权,并不违反rust借用规则检查,但是编译就是不过。在排查问题的时候把问题的焦点放到了addVal方法的vals和person参数上了,看漏了一个vals的元素也是引用,由于vals的元素是引用,所以vals向量的生命周期应该小于借用关系的生命周期,而vals到main函数的结尾都还存活,所以借用关系至少要持续到函数结尾,又由于vals的借用和vals的元素声明成了相同的生命周期,所以vals的借用关系也是持续到main函数结尾的,所以,一直处于借用状态,并没有归还,不能再借用共享引用,导致编译报错。
最后经过大佬点播,把vals引用参数和vals的元素生命周期声明成不同的生命周期,就通过编译了。
最后addVal函数的签名为:

fn addVal<'a, 'b>(vals: &'a mut Vec<&'b str>, person: &'b Person)

 rust是我目前遇到的最值得学习的编程语言,我对它的喜爱超过了之前的lua,路漫漫其修远兮,继续探索之路。

原文地址:https://www.cnblogs.com/omega8/p/12218687.html