• 我的第一篇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,路漫漫其修远兮,继续探索之路。

  • 相关阅读:
    由@Convert注解引出的jackson对枚举的反序列化规则
    List.contains()与自动拆箱
    Utf-8+Bom编码导致的读取数据部分异常问题
    ResouceUtils.getFile()取不到Jar中资源文件源码小结
    Java自动装箱中的缓存原理
    Javaconfig形式配置Dubbo多注册中心
    logback多环境配置
    Spring @Scheduled @Async联合实现调度任务(2017.11.28更新)
    Nginx的Access日志记录的时机
    Mysql索引引起的死锁
  • 原文地址:https://www.cnblogs.com/omega8/p/12218687.html
Copyright © 2020-2023  润新知