近段时间在学习研究Rust。都说Rust学习曲线陡峭,感觉果然如此。之前学习Go,基本上没有专门去看语法,只是在需要的时候上网查一查,再花点时间看看大型的开源软件项目,差不多就可以写生产级别的代码了。而Rust则不然,至少本人花了差不多两三周的时间专门学习语法,然而去看开源的项目依然觉得很吃力,又花了一些时间才搞明白了Rust的几种编码模式,特别是异步模式,又分为poll循环的方式、combinator方式和.await协程的方式,各种坑比较多,填坑的过程还是比较费劲的。
整个大约两个多月学习过程中,曾经碰到过很多的问题,在网上阅读过很多的文章寻找答案,也和有经验的开发者进行过微信交流,总体感觉Rust还是一个正在发展中的语言,不同版本之间有一些差异,特别是Rust并没有提供一个非常完整runtime(也可以理解成是开放的,提供了各种选项),异步编程模式还有tokio和async-std这样的阵营分裂,网上相关的资料也是鱼龙混杂,对于初学者而言,有可能迷失在一些错误的描述或者相互矛盾的各种资料中,走一段冤枉路。故而,在这里用文字将自己的学习历程和心得体会整理出来,希望能够对他人有所帮助。
语法
相对而言,Rust的语法是挺特别的。因为有生存周期和借用检查这类独有的概念,所以语法上看上去比较复杂。作为一种现代编程语言,大量使用了泛型,但是也带来代码可读性较差的问题。相信所有的初学者都会对层层包裹的泛型参数及其限定感到头痛,可能需要花费一段时间来适应一下。而枚举类型Option<T>替代Null,错误处理Result<T,E>也是有特色的地方,然也导致相关的代码略显臃肿(个人体会,完成相同功能,Rust代码篇幅总是较之Go代码明显更长)。总之,学习Rust,语法是第一道门槛,需要一点耐心和韧性。
“安全”和“高性能”
所有权概念解决内存安全和GC的问题,是Rust语言的基石,也是整个系统的亮点。结合Type系统和Trait限定(Send, Sync),Rust用一种不那么直观但极为优雅的方式规定了多线程编码的基本要素。也就是说,除非写Unsafe,否则程序员无法制造出C/C++中常见的内存double free问题,也没机会写出线程不安全的代码,这类问题在大型软件项目后期基本都是灾难。然而,Rust并不能解决代码的逻辑错误。我们一样会碰到内存泄漏,多线程死锁之类的问题。一般看来,多线程死锁差不多也是灾难级别的问题。此外,关于高性能,很多时候是Unsafe的同义词,而使用Unsafe,Rust就退化为C语言。因此,对于Rust“安全”和“高性能”,需要有一个辩证的认识。
同步,异步
Rust提供开放的选项,怎么写代码是程序员的选择。同步的代码比较直接,掌握了Rust语法就可以看懂,容易上手。当然,如果仅仅是同步模式多线程的代码,Rust差不多相当于一个增强版的C++。同步模式的代码与异步模式代码的观感上差别很大。或者说,没有专门学习过异步编程模式,很可能完全看不懂异步的代码。异步模式对于重视I/O吞吐的应用场景意义重大,主流编程语言纷纷加入了异步模式的支持,特别是Go原生支持且只支持异步模式。然而,Rust异步编程模式需要学习除语法之外的更多内容,多了不少新的概念,还有不同风格写法,掌握起来有一定难度。类库还有诸如 tokio 与 async-std 的不同阵营,无疑很大程度地又增加了学习的难度。而无论 tokio 或是 async-std,成熟度都有欠缺,远远不如Go简单易用。但是对于使用异步编程模式的开发人员,还是很有必要了解异步模式的工作原理和技术实现,否则,面对一些相对复杂的问题可能就束手无策了。
第三方类库
Rust因为其高门槛,注定就是小众的。目前来看,第三方类库能够提供的轮子数量有限,质量堪忧,与同样号称系统编程语言的Go差距巨大,在劳动生产率上无法相提并论。如果从头开始一个大型项目,是否选用Rust,取舍值得三思。究竟需要“安全”和“高性能”,还是快速开发,尽早交付?
开发工具
这一点需要用力吐槽。相较于使用Goland进行Go开发的轻松愉悦,使用Clion进行Rust开发可谓惨不忍睹。编辑器无法很好地理解或展开Rust宏,因此语法提示等功能都会失效,有点盲人摸象的感觉。调试器断点不可靠,很多时候被迫祭出printf大法,调用栈很难提供有用的信息,被层层包裹的变量无法查看,等等。如果说Goland可以打9分,那么Clion只能是不及格。另外,曾经尝试过VSCode,感觉还不如Clion。展望未来,随着Rust被更多认可并得到更多支持,开发工具的改善和提高是可以预期的,特别是调试器,针对Rust做相关的优化后相信体验会大幅改善。然而,因为Rust语法的复杂性以及大量依赖泛型的特性,冀望Rust开发工具的体验效果达到Go开发工具的程度,估计不大现实。
网上各种资料
相较于广泛流行的Java,Go等语言,Rust的生态不可同日而语,相关资料、文献不够丰富。特别缺乏高质量的中文原创内容。不少的翻译文章,原文内容丰富,质量很高,但译者可能并没有完全理解原文的精髓,很多地方直译了事,没能讲到点子上。这时候,建议读者找到原文对比阅读。几位Rust核心开发人员的博客,建议关注
Rust 相关的文章或教程推荐
入门教程:
• Book:经典入门教程。个人觉得过于简练,略过了很多内容
• 深入浅出Rust:中文书籍,作为语法学习很不错。内容详尽,个别地方稍显陈旧
异步编程:
• The Future With Futures:文章有点久远,但还是值得一读
• Asynchronous Programming in Rust:tokio 团队关于异步编程的教程,系统性地讲解了异步编程的来龙去脉
• Async programming in Rust with async-std:async-std 团队关于异步编程的教程。里面有一个非常棒的设计实现聊天程序的教程案例。这不是一个简单的示例,至少不是用unwrap来写的简单示例…
博客:
• withoutboats’ Blog :著名的withoutboats,博客中有非常多内容,方方面面
• stjepang’s Blog:crossbeam,smol 的作者。smol 现在是 async-std 的底层支撑。作者博客中详尽地介绍了 executor 的实现细节
• snoyman’s Blog: 讲解了async fn 的原理,值得一读。博客中有一系列关于Rust的精彩文章
中文:
• 最近学写 async/await 被 Rust 毒打的经验:这篇文章作者写得非常生动具体,里面提到的问题都是亲身体会
• Rust Async: 深度分析AtomicWaker:关于waker的深入分析