Rust语言(一) 开篇
1 入坑
作为一只散养的程序员,当手上的时间变得充裕就会想去学点新的技术。除了品尝美食,补番,写开源项目,学一门新的语言吸收其中的优点也是一个不错的选择。Rust作为连续4年最喜欢的语言,加上系统级语言,自然值得一学。
2 为什么Rust
Rust语言还是比较年轻的一门语言,主要的竞争对手是C/C++。作为一门新秀语言,自然需要有一些比较NB的特点,不然怎么打败这些都快50岁的老家活呢🤪
2.1 内存安全&类型安全
首先Rust能保证没有野指针,悬挂指针等,这种简直就是挖坑让你跳。所以也不会内存泄漏(只要不是在unsafe block里面的),在C/C++大家都知道手动管理内存有多麻烦,毕竟是人写的,只要人就会犯错,犯错还不好找,找不到就是crash,crash就是Bug,可能会影响绩效的,绩效不好钱就少了,还怎么愉快的买买买呢。
类型安全可以保证不会传个什么都给你计算,可以通过编译器提前给出编译错误,而不是等到执行的时候才发现,可以参考Java这一类的语言。
2.2 没有GC
早期的Rust虽然有垃圾回收,但是后面改用了引用计数(不需要手动释放),在变量离开作用域时会自动释放。没有GC意味着没有额外的开销,也不会存在新生代老生代的问题。作为GC届的代表Java,最被诟病的就是性能损耗,尤其是GC时的抖动,都可以作为单独的优化点。
没了GC,就像没有枷锁束缚的战士,性能也是碾压各种GC语言,比如Java,Go,python等,甚至有些benchmark在c语言之上。
2.3 天然支持并发
在Rust设计理念里面,对象是不可变的,默认是let修饰,如果想要变成可变,不是像Kotlin一样用另外的关键字var,而是在let后面加**mut,**在某个时间点能有多个读操作或一个写操作。
2.4 表达能力匹及动态语言
这个可能是我最喜欢的一个特点了,完全是参考了函数式语言的特点。
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). _ => (), } }
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()函数,并且可以直接调用,特别适合模版代码的时候,不需要重复的写很多这种代码,极大提高工作效率。另外也可以传入表达式,对!表达式,整个表达式都是作为参数传入,有点动态语言或者函数式语言的意思了😎
2.5 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`.
2.6 适用于跨平台及资源紧张的嵌入式平台
本身没有GC,也不依赖于虚拟机,所以可以作为跨平台库的选项。再者跨平台库需要很高的稳定性,不然错误排查是相当困难。
2.7 支持泛型
泛型作为现代语言基本标配,Rust有也不算什么优势,而是对标于Go语言👎👎
3 缺点
没有!!!!
|
|
|
|
|
|
|
|
当然不可能,但是列那么多缺点,影响我学习的热情,而且学习曲线还相当陡峭,所以大家自行Google吧