我用 Rust 重写了博客,谈谈我眼中的 Rust. 内容略长.

2017-09-27 19:49:47 +08:00
 samray

前言

我已经学习 Rust 有挺长的一段时间了,一直想用 Rust 来写点东西,但是缺乏好的想法; 有些想法自我感觉良好,但是又没有能力实现 (比如,写一个操作系统?), 所以最后我决 定还是拿我的博客来做实验品吧。我原来的博客 是 基于 Github Page 和 Org mode 实现的静态博客,略显简单。所以我就觉得用 Rust 来写 个新的博客。

我眼中的 Rust

前后花了一个月的空余时间来写这个博客,写完这个博客之后,我觉得我应该算是有点 Rust 的编程经验了 ;-). 在学习 Rust 和使用 Rust 的时候,我总是将 Rust 和我平时使 用的语言进行对比。一段时间下来,我对使用 Rust 的感悟越来越多,所以我谈谈我眼中的 Rust

优点

内存安全

谈及 Rust, 首先想到的一定是内存安全,正如官网对 Rust 的定义:

Rust is a systems programming language that runs blazingly fast, prevents segfaults, and guarantees thread safety.

这个也是 Rust 对比其他的语言最大的亮点之一. 众所周知,在 Rust 之前的其他编程语言 管理内存的方式无非是以使用垃圾回收算法管理内存(代表就是 Java 和 Python), 或者是 C/C++ 手工管理内存。手工管理内存非常容易出现问题,即使是非常有经验的工程师也不能 写出完全没内存问题的代码,毕竟人总是免不了出错。但是使用垃圾回收算法就一定会有运 行时和垃圾回收时的停顿,这就不适合系统编程了。而 Rust 通过新加入的 生命周期 (lifetime)和所有权 (Ownership) 特性,就可以实现内存的自动回收,并且无需运行时, 可以大大地避免出现类似内存泄漏或者时悬停指针之类的问题

编译器

据说,在 Rust 的编译器设计理念里,编译器可以检查的,就无需程序员操心。并且因为 Rust 所倡导的安全的概念,所以它的编译器会做尽可能多的检查,争取在编译期就发现问 题。此外 Rust 的编译信息还非常友好和详细

error[E0308]: mismatched types
  --> src/main.rs:72:32
   |
11 |     let url = match Url::parse(matches.value_of("URL")) {
   |                                ^^^^^^^^^^^^^^^^^^^^^^^ expected &str, found enum `std::option::Option`
   |
   = note: expected type `&str`
              found type `std::option::Option<&str>`
   = help: here are some functions which might fulfill your needs:
           - .unwrap()
           - .unwrap_or_default()

error: aborting due to previous error

error: Could not compile `blog`.

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


Rust 编译器就像导师一样耳提面命,为你指出代码中的问题(但是有时候,我觉得 Rust 的编译器也像导 师一样,太啰嗦了 !-_-)

表达能力强

Rust 不同于衍生自 C 的 Java, Go, Python 等语言,Rust 更多地吸取了 Ocaml, Haskell, Scheme 等函数式语言的特性。对于习惯了 C 系语言的同学而言,Rust 算是打开 了一个新的大门。

match

Rust 具有非常强大的表达能力,比如说 match, 这个类似 C 里面的 switch,但是强大得多. 首先看一下类似 switch 的功能:

enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter,
}

fn value_in_cents(coin: Coin) -> u32 {
    match coin {
        Coin::Penny => 1,
        Coin::Nickel => 5,
        Coin::Dime => 10,
        Coin::Quarter => 25,
    }
}

这个是 The Rust Programming Book 的例子,作用是列举所有的枚举值,但是似乎也没有比 switch 神奇到哪里去。但是 match像其他的函数式语言那样,可以提供模式匹配的能力,为复杂的类型系统提供一个简单轻松的解构能力。例如对 struct 进行解构:

struct Point {
    x: i64,
    y: i64,
}
let point = Point { x: 0, y: 0 };
match point {
    Point { x, y } => println!("({},{})", x, y),
}

这样,对 使用 match 就可以得到 Point的内部值

macro

Rust 也有 宏系统 (macro), 不是类似 C 的那种简单文本替换的宏,而是类似 Lisp 系语 言的宏,使用过 Lisp 方言的同学自然会明白宏的强大,《黑客与画家》的作者 Paul Gram 也是宏的忠实粉丝。比如我使用宏来创建一个函数:

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);

使用上面的定义的宏,我就创建了一个 foo()bar() 函数,然后就可以直接调用:

fn main() {
    foo();
    bar();
}

Rust 的宏系统极具表现力 完整例子参见 rust by example

工具链

不得不说,Rust 的工具链真的让程序员非常舒心

Cargo

Cargo 是 Rust 的构造系统和包管理器,开发者可以用 Cargo 下 载相应的依赖和构造代码。Cargo 非常容易上手,但是功能确是非常强大,Cargo 还可以帮 开发者设置相应的单元测试和基准测试,所以使用 Cargo 进行单元测试和基准测试是非常 省心。Cargo 是多合一的一站式工具,也是同类工具中,我使用过的最强大的

Rustup

rustup 是 Rust 的一个安装器,使用 rustup 来更新 Rust 的编译器,它跟 Python 的 virtualenv 有点像,可以维护不同版本的 Rust 编译器,例如 stable, nightly,beta 等

rust-clippy

rust-clippy 是 Rust 的一个静 态代码分析工具,虽说 Rust 的编译器在分析 Rust 代码上已经做了非常多的工作了,但是 rust-clippy 可以帮你更进一步,编写出更好的代码。总会有一些代码可以进行简化以提高 代码的可读性,或者是更符合最佳实践,而 rust-clippy 就是会给你相应的提示,以协助 你编写出更好的代码。

性能强劲

Rust 强劲的性能也是它非常大的亮点之一,记得我学习 Rust 的其中一个原因就是它的性 能,因为我熟悉的 Python 虽然优点非常多,但是性能一直被人垢病. 而 Rust 其中的一个 设计理念就是实现高并发,充分利用好现代电脑的多核特性. Rust 的目标是性能方面超越 C 语言,可能这个目标在很多人看来都很可笑. 但是很多基准测试都表明 Rust 的性能和 C 已经相差不大,考虑到 Rust 本身就是为了现代多核电脑设计的编程语言,而 C 还是上世 纪 70 年代的产物,即使是天才般的发明,现在也不免追不上莫尔定律的脚步,况且 Rust 还是处在婴儿期,而 C 已经非常成熟,例如 GCC 这样的编译器也对 C 语言做了非常多的 优化,C 语言性能方面的增长已经很有限了。所以如果 Rust 真的能利用好多核的性能,未 来真的可期

友好的社区

这个应该不算是 Rust 的一个优点,但是 Rust 社区让我在编写 Rust 过程深深受益。我编 写的博客使用的 Web 框架是 Rocket, 数据库层的 ORM 是 Diesel, 因为框架和编程语言都非常新,虽说他们的文档都非常完 整,但是难免会有覆盖不到的地方,所以总会有一些遇到的问题我不知道怎么解决。所以我 经常向社区求助,在 Reddit 上发贴,或者是在 Gitter 上找人求助,又或者是在 Github 上面求助,在社区的朋友的帮助下,我最后都能解决问题。社区的朋友都非常友好和乐于帮 忙,即使我问的问题很菜鸟,但是他们都一一耐心做答。Rust 社区给我的感觉和 Emacs 社 区给我的感觉很相似,社区人数少,但是素质非常高,非常友好。

不足

现在我来说说 Rust 的不足或者说是劣势

陡峭的学习曲綫

前面提到 Rust 为了实现内存无运行时的自动管理,引入了独创的生命周期 (lifetime)和 所有权 (ownership), 对于学习 Rust 的同学来说,这是必须跨过去的坎,接着还有类似引 用 (Reference),租借 (Borrow) 这些特性,真的令人望而生畏。而 Rust 的很多新的特性 都是没办法从已有的编程语言那里找到类似的特性的,所以必须以 Rust 的思维去学习 Rust, 而不能抱着 Java 或者 C++ 的思维的学,因为这样一定会撞得头破血流,久攻 不下,就很容易放弃

还是编译器

没错,Rust 的不足,编译器也有一份子。前面提到 Rust 是会尽可能地检查你的代码,把 BUG 扼杀在编译期,所以就会导致两个问题. 问题一: 很多东西编译器都要管,所以你的代 码就必须写得符合编译器的要求,不然编译器就不会让你通过,所以每次编译都想撞墙,怎 么这个编译不通过,那个编译也不通过;如果你的代码编译通过了,它运行就比较少会出现 问题;问题二:因为要做尽量多的检查,所以导致编译的时间非常长,经常是改动了一小点 代码,重新编译就要 10s 以上, 而我的机器都已经是 E5 的 CPU 加 32G 的内存了。

尚不成熟的生态环境

虽说 Rust 现在发展迅速,但是 Rust 的生态还没有起来,很多优质的类库还是欠缺,很多 现有的类库还不成熟,例如我现在使用的 Rocket 框架还只是 0.3, Diesel 还只是 0.16.0 ,很多我需要的功能都没有,比如 Diesel 这个 ORM 还没无法进行 Rust 的 enum 和 Postgres 的 enum 的映射,一些复杂的查询还不支持,只能使用 sql 进行操作。其他类库的版本如图:

缺乏 IDE

现在 Rust 没有比较成熟的 IDE, 现在我使用 Emacs 编写 Rust, 配合 Racer 这个 Rust 代码补全工具,但是 Racer 只是能补全标准类库的代码,对于下载下来的依赖类库,就无 能为力,所以我写代码都只能对着 API 文档编写,然后编译,出了问题再修改。虽说 Rust 团队现在基于 LSP 在开发 RLS, 但是我写 Rust 的感觉就好像我使用编辑器写 Java 的感 觉一样,实在是效率太低,代码补全,语法提示功能太弱了。

中文社区

虽说这个与 Rust 本身无关,不过我只是想吐嘈一下,Rust 的中文社区几乎没有,我的所 有 Rust 问题都是在 Reddit, Github, Gitter, IRC 上面解决的. 我只是希望 Rust 中文社 区也可以强大起来。人数应该不是什么大的原因,像 Emacs 的用户那么少,Emacs 的 中 文社区 一样很繁荣,这个算是我的一个希冀吧

小结

其实学习 Rust 还是很有收获的, 不是说,如果这种语言没有改变你对编程的看法,那它就 不值得你学。这么看来,Rust 还是值得我学习的,Rust 现在给我的感觉跟 Emacs/Vim 很 相似,它很强大,但是由于学习曲线等诸多原因,游离于主流之外,但是它的强大和它的美 只有你亲身学习,亲身经历才能体会到的。这就是如鱼饮水,冷暖自知吧。最后贴上几张博客截图

博客地址: samray's blog

Github 地址: blog

50944 次点击
所在节点    分享创造
86 条回复
fy
2017-09-27 20:37:08 +08:00
折腾不易 且行且珍惜

LZ 行动力不错
samray
2017-09-27 20:53:27 +08:00
谢谢.编程最不能缺少的就是实践和折腾了 :)
marknote
2017-09-27 21:25:37 +08:00
不错!加油!
flaneurse
2017-09-27 21:33:16 +08:00
学习了
samray
2017-09-27 21:35:57 +08:00
@marknote 共勉咯
samray
2017-09-27 21:36:27 +08:00
@flaneurse 是学习了 Rust 了么?哈哈
davidqw
2017-09-27 21:41:11 +08:00
靠谱,不少区块链的应用都开始用 rust 开发了,内存安全很重要
samray
2017-09-27 21:50:24 +08:00
不止是区块链,Firefox 的引擎也是用 Rust 重写了,现在部分评测性能已经超过了 Chrome, 详见 https://blog.mozilla.org/blog/2017/09/26/firefox-quantum-beta-developer-edition/. 其实我觉得 Rust 真的很强大的,但是它没有 Golang 那样容易上手,也没有 Golang 那样的爹来推广,所以普及度就不如 Golang.
secondwtq
2017-09-27 21:53:46 +08:00
楼主貌似忘了提 Algebraic Data Type 了
十天前简单梳理了一下,静态类型的 imperative programming language 里面,“能用”并且有点名气的只有 Rust,还有个四不像的 Scala
我对“能用”的要求不高,Algebraic Data Type + Pattern Matching
droiz
2017-09-27 22:08:22 +08:00
加油楼主!学习了
samray
2017-09-27 22:09:57 +08:00
@secondwtq 我在写博客的过程中没有用到 Algebraic Data Type, 所以我就没展开说自己的看法了,不过我之前看过 https://blog.rust-lang.org/2015/04/17/Enums-match-mutation-and-moves.html 这篇文章也有提及 Rust 的 Algebraic Data Type, 不过 Rust 的 Pattern Matching 就真的非常强大,除了我上面列举的,还可以配合 Result 和 Option 使用,我觉得 Option 是另外一个非常强大的点,完全杜绝了 Java 的空指针,而 Result 的错误处理就又是和 Java/Python 异常系统完全不同的 Error Handling 机制
samray
2017-09-27 22:10:44 +08:00
@droiz 互相学习 :)
cuebyte
2017-09-27 22:14:42 +08:00
@secondwtq 要让我选,Scala 还是比 Rust 更容易写。
ipconfiger
2017-09-27 22:46:55 +08:00
第一, 放国外的, 太慢, 根本体会不出到底快在那里, 第二, 其实应该重写 Hexo 啊, 或者 Jekyll、Octopress 之类的
楼举觉得呢
sunjourney
2017-09-27 22:49:41 +08:00
Firefox 家的东西,当然要自己用了。Rust 写博客,算激光炮打蚊子吗?
sunjourney
2017-09-27 22:51:49 +08:00
访问居然要 fq。。。是被盯上了吗
samray
2017-09-27 23:10:18 +08:00
@ipconfiger 放国外是因为我不想备案,这个真的烦人.其次嘛,一个博客快也不会快到哪里去的,我主要谈的是我写博客过程中的体会.很多东西都是由小见大的,我没有 Rust 真正写过什么,我也不好意思来说感受吧.至于 Hexo,这个建议很有趣,真的可以有空想想怎么写.
samray
2017-09-27 23:13:29 +08:00
@sunjourney 要 fq 可能是因为我服务器和域名都是国外买的吧,这个就看 qiang 的心情了,我也决定不了,摊手无奈脸.
至于是不是用激光炮打蚊子,激光炮可以用来打蚊子,和真的用激光炮来打蚊子还是区别的.用激光炮打蚊子了,你对蚊子和激光炮都会有切身的体会了,接下来要用激光炮打其他东西就会有更大的把握了 :)
dbw9580
2017-09-28 00:26:00 +08:00
断断续续看过将近半个月的 the rust book,rust by example,上手想实现一下链表,结果发现 rust 对指针的限制催生出了很多 c 里不会有的结构,比如在堆上分配内存要用 Box 这种数据类型,共享所有权用 Rc,内部可变性要用 Cell 和 RefCell,从 C 过来一脸懵逼,原本很简单的施工推倒重来了不知多少遍。。
lrxiao
2017-09-28 01:00:28 +08:00
lz rust primer 讲的 trait object safety 到底是个什么概念 我看到那一脸懵逼

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/394146

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX