入坑

作为一只散养的程序员,当手上的时间变得充裕就会想去学点新的技术。除了品尝美食,补番,写开源项目,学一门新的语言吸收其中的优点也是一个不错的选择。Rust作为连续4年最喜欢的语言,加上系统级语言,自然值得一学。

为什么Rust

Rust语言还是比较年轻的一门语言,主要的竞争对手是C/C++。作为一门新秀语言,自然需要有一些比较NB的特点,不然怎么打败这些都快50岁的老家活呢🤪

内存安全&类型安全

首先Rust能保证没有野指针,悬挂指针等,这种简直就是挖坑让你跳。所以也不会内存泄漏(只要不是在unsafe block里面的),在C/C++大家都知道手动管理内存有多麻烦,毕竟是人写的,只要人就会犯错,犯错还不好找,找不到就是crash,crash就是Bug,可能会影响绩效的,绩效不好钱就少了,还怎么愉快的买买买呢。

类型安全可以保证不会传个什么都给你计算,可以通过编译器提前给出编译错误,而不是等到执行的时候才发现,可以参考Java这一类的语言。

没有GC

早期的Rust虽然有垃圾回收,但是后面改用了引用计数(不需要手动释放),在变量离开作用域时会自动释放。没有GC意味着没有额外的开销,也不会存在新生代老生代的问题。作为GC届的代表Java,最被诟病的就是性能损耗,尤其是GC时的抖动,都可以作为单独的优化点。

没了GC,就像没有枷锁束缚的战士,性能也是碾压各种GC语言,比如Java,Go,python等,甚至有些benchmark在c语言之上。

source

天然支持并发

在Rust设计理念里面,对象是不可变的,默认是let修饰,如果想要变成可变,不是像Kotlin一样用另外的关键字var,而是在let后面加**mut,**在某个时间点能有多个读操作或一个写操作。

表达能力匹及动态语言

这个可能是我最喜欢的一个特点了,完全是参考了函数式语言的特点。

  1. match表达式

    // `allow` required to silence warnings because only
    // one variant is used.
    #[allow(dead_code)]
    enum Color {
        // These 3 are specified solely by their name.
        Red,
        Blue,
        Green,
        // These likewise tie `u32` tuples to different names: color models.
        RGB(u32, u32, u32),
        HSV(u32, u32, u32),
        HSL(u32, u32, u32),
        CMY(u32, u32, u32),
        CMYK(u32, u32, u32, u32),
    }
    
    fn main() {
        let color = Color::RGB(122, 17, 40);
        // TODO ^ Try different variants for `color`
    
        println!("What color is it?");
        // An `enum` can be destructured using a `match`.
        match color {
            Color::Red   => println!("The color is Red!"),
            Color::Blue  => println!("The color is Blue!"),
            Color::Green => println!("The color is Green!"),
            Color::RGB(r, g, b) =>
                println!("Red: {}, green: {}, and blue: {}!", r, g, b),
            Color::HSV(h, s, v) =>
                println!("Hue: {}, saturation: {}, value: {}!", h, s, v),
            Color::HSL(h, s, l) =>
                println!("Hue: {}, saturation: {}, lightness: {}!", h, s, l),
            Color::CMY(c, m, y) =>
                println!("Cyan: {}, magenta: {}, yellow: {}!", c, m, y),
            Color::CMYK(c, m, y, k) =>
                println!("Cyan: {}, magenta: {}, yellow: {}, key (black): {}!",
                    c, m, y, k),
            // Don't need another arm because all variants have been examined
        }
    }
    

    这是一个用颜色来匹配的例子,不仅可以匹配枚举(enum),还能匹配枚举构造函数和参数。另外也能解构一些常用的集合类

    let pair = (0, -2);
        // TODO ^ Try different values for `pair`
    
        println!("Tell me about {:?}", pair);
        // Match can be used to destructure a tuple
        match pair {
            // Destructure the second
            (0, y) => println!("First is `0` and `y` is `{:?}`", y),
            (x, 0) => println!("`x` is `{:?}` and last is `0`", x),
            _      => println!("It doesn't matter what they are"),
            // `_` means don't bind the value to a variable
        }
    

    当然还有别的match特性,比如绑定等等。

    // A function `age` which returns a `u32`.
    fn age() -> u32 {
        15
    }
    
    fn main() {
        println!("Tell me what type of person you are");
    
        match age() {
            0             => println!("I haven't celebrated my first birthday yet"),
            // Could `match` 1 ..= 12 directly but then what age
            // would the child be? Instead, bind to `n` for the
            // sequence of 1 ..= 12. Now the age can be reported.
            n @ 1  ..= 12 => println!("I'm a child of age {:?}", n),
            n @ 13 ..= 19 => println!("I'm a teen of age {:?}", n),
            // Nothing bound. Return the result.
            n             => println!("I'm an old person of age {:?}", n),
        }
    }
    
    fn some_number() -> Option<u32> {
        Some(42)
    }
    
    fn main() {
        match some_number() {
            // Got `Some` variant, match if its value, bound to `n`,
            // is equal to 42.
            Some(n @ 42) => println!("The Answer: {}!", n),
            // Match any other number.
            Some(n)      => println!("Not interesting... {}", n),
            // Match anything else (`None` variant).
            _            => (),
        }
    }
    
  2. macro(宏)

    Rust的宏系统,不是C的那种简单替换,比如把False替换成True这种傻事。而是Lisp那种宏,你可以利用宏动态创建函数。

    macro_rules! create_function {
        // This macro takes an argument of designator `ident` and
        // creates a function named `$func_name`.
        // The `ident` designator is used for variable/function names.
        ($func_name:ident) => {
            fn $func_name() {
                // The `stringify!` macro converts an `ident` into a string.
                println!("You called {:?}()",
                         stringify!($func_name));
            }
        };
    }
    
    // Create functions named `foo` and `bar` with the above macro.
    create_function!(foo);
    create_function!(bar);
    
    macro_rules! print_result {
        // This macro takes an expression of type `expr` and prints
        // it as a string along with its result.
        // The `expr` designator is used for expressions.
        ($expression:expr) => {
            // `stringify!` will convert the expression *as it is* into a string.
            println!("{:?} = {:?}",
                     stringify!($expression),
                     $expression);
        };
    }
    
    fn main() {
        foo();
        bar();
    
        print_result!(1u32 + 1);
    
        // Recall that blocks are expressions too!
        print_result!({
            let x = 1u32;
    
            x * x + 2 * x - 1
        });
    }
    
    //输出
    You called "foo"()
    You called "bar"()
    "1u32 + 1" = 2
    "{ let x = 1u32; x * x + 2 * x - 1 }" = 2
    

    上面就是利用宏创建了foo()和bar()函数,并且可以直接调用,特别适合模版代码的时候,不需要重复的写很多这种代码,极大提高工作效率。另外也可以传入表达式,对!表达式,整个表达式都是作为参数传入,有点动态语言或者函数式语言的意思了😎

AOT编译

Rust语言强大的另一个地方就是编译器,凡是不确定的都抛错误让你去解决,会精确到某一行某一列和你说什么错误,相当的精确(啰嗦)

error[E0308]: mismatched types
 --> p1.rs:8:33
  |
8 |             if map.contains_key(expect) {
  |                                 ^^^^^^
  |                                 |
  |                                 expected `&i32`, found `i32`
  |                                 help: consider borrowing here: `&expect`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.

适用于跨平台及资源紧张的嵌入式平台

本身没有GC,也不依赖于虚拟机,所以可以作为跨平台库的选项。再者跨平台库需要很高的稳定性,不然错误排查是相当困难。

支持泛型

泛型作为现代语言基本标配,Rust有也不算什么优势,而是对标于Go语言👎👎

缺点

没有!!!!

|

|

|

|

|

|

|

|

当然不可能,但是列那么多缺点,影响我学习的热情,而且学习曲线还相当陡峭,所以大家自行Google吧

https://www.google.com/search?q=rust+disadvantages