当Rust 1.0发布时,我去官方网站了解了一下Rust语言,发现它的主要特点有以下几方面:
- 系统级语言
- 无GC
- 基于LLVM
- 内存安全
- 强类型+静态类型
- 混合编程范式
- 零成本抽象
- 线程安全
我一下子就被这些鲜明的特性“击中”了,从此开始了Rust的学习。
1、为什么是Rust ?
社区中有人模仿阿西莫夫的机器人三大定律,总结了程序的三大定律:
- 程序必须正确。
- 程序必须可维护,但不能违反第一条定律。
- 程序必须高效,但不能违反前两条定律。
程序的正确性,一方面可以理解为该程序满足了实际的问题需求, 另一方面是指满足了它自身的程序规约。那么如何保证程序的正确性呢?
- 首先,可以通过对程序的各种测试、断言和错误处理机制,来保证其满足实际的问题需求。
- 其次,在数学和计算机科学已经融合的今天, 通过较为成熟的类型理论即可保证程序自身的规约正确。
以Ruby 语言为例,程序的正确性必须依赖于开发者的水平,并需要大量的测试代码来保证正确性。即便在100%测试覆盖率的条件下,也经常会遇到NilError之类的空指针问题。也就是说,Ruby程序自身的正确性还没有得到保证。以此类推,C、C++、Python、Java、JavaScript等语言都有同样的问题。
而函数式编程语言在这方面要好很多,尤其是号称纯函数式的Haskell 语言,它具有融合了范畴理论的类型系统,利用了范畴理论自身的代数性质和定律保证了程序自身的正确性。然而,Haskell也有比较 明显的缺点,比如它不满足上述第三条定律,运行效率不高。
反观Rust语言,对程序的三定律支持得恰到好处。
- 程序必须正确、高效:它借鉴了Haskell的类型系统,保证了程序的正确性。但还不止于此,在类型系统的基础上,Rust借鉴了现代C++的内存管理机制,建立了所有权系统。不仅保证了类型安全,还保证了内存安全。同时,也解决了多线程并发编程中的数据竞争问题,默认线程安全。
- 程序必须可维护:再来看代码的可维护性,Rust代码的可读性和抽象能力都是一流的。不仅拥有高的开发效率,还拥有可以和C/C++媲美的性能。
当然,没有银弹,但Rust就是我目前想要的语言。 目前Rust被陆续应用在区块链、游戏、WebAssembly技术、机器学习、分布式数据库(如TiDB自有的分布式key-value存储系统TiKV组件)、网络服务基础设施、Web框架、操作系统和嵌入式等领域。时代在变化,未来的互联网需要的是安全和性能并重的语言,Rust必然会在其中大放异彩。
2、学习Rust能带来了什么收获 ?
- Rust是一门现代化的语言,融合了多种语言特性,而且Rust语言可以应用的领域范围非常广泛。在学习Rust的过程中,发现自己的编程能力的短板。突破这些短板的过程实际上就是一次自我提升的过程。
- Rust 是一门成长中的新语言,学习 Rust,跟随 Rust 一起成长,可以体验并参与到一门真正工业化语言的发展进程中,感觉就像在创造历史。虽然我并未给Rust语言提交过PR,但也为Rust语言和社区多次提交过Bug,以及文档和工具的改进意见。
- Rust自身作为一个开源项目,算得上是开源社区中的“明星”项目了。学习Rust的过程加深了我对开源社区的认识,也开拓了我的眼界。
3、前言
在我刚开始学习Rust的时候,在社区里听到最多的声音就是“Rust学习曲线陡”。已经有一定编程经验的人在学习一门新语言时,都喜欢直接上手写代码,因为这样可以快速体验这门语言的特色。对于大多数语言来说,这样确实可以达到一定的学习目的。但是当他们在初次学习Rust的时候,就很难通过直接上手来体验这种快感。
我第一次学习Rust时就遇到了这样的情况。我按以往的编程经验直接写下了代码,但是编译无法通过;可是有时候简单调换两行代码的顺序,程序就能顺利编译成功了,这让我非常困惑。我想这也是大多数人感觉“Rust学习曲线陡”的原因吧。经过和Rust编译器的多次“斗争”之后,我不得不重新反思自己的学习方法。看样子,Rust 编译器暗含了某种规则,只要程序员违反了这些规则,它就会检查出来并阻止你。这就意味着,作为程序员,你必须主动理解并遵守这些规则,编译器才能和你“化敌为友”。
所以,我就开始了对Rust的第二轮学习,忘掉自己以往的所学,抱着初学者的心态,从零开始系统地学习Rust。然而,事情并没有这么简单。
Rust官方虽然提供了Rust Book,但是内容的组织非常不友好,基本就是对知识点的罗列,系统性比较差。后来官方也意识到了这个问题,推出了第2版的Rust Book,内容组织方面改善了很多,对学习者也非常 友好,但系统性还是差了点。后来又看了国内Rust社区组织群友们合著 的Rust Primer,以及国外的Programming Rust,我才对Rust建立了基本 的认知体系。
直到此时,我才意识到一个重要的问题:Rust学习曲线陡的根本原因?
- Rust语言融合了多种语言特性和多种编程范式。这就意味着,Rust涉及的知识范围非常广泛,涵盖了面向对象、函数式、泛型、底层内存管理、类型系统、设计模式等知识。
- 从底层到上层抽象,从模式到工程化健壮性,无所不包。可以说,Rust是编程语言发展至今的集大成者。对于大多数Rust语言的初学者来说,他掌握的知识体系范围是小于Rust所包含的知识量的,所以在学习Rust的过程中会遇到无法理解的内容。
我在学习Rust之前,所掌握的编程语言知识体系大多是和拥有GC的动态语言相关的,对于底层内存管理知之甚少。所以在我学习Rust所有权的时候,就很难理解这种机制对于内存安全的意义所在;而我所认识的一些拥有 C 语言编程经验的朋友,在学习 Rust 时面临的问题是,难以理解Rust支持的上层抽象,对他们来说,Rust中融合的类型系统和编程范式就是他们学习道路上的“拦路虎”;对于拥有 Haskell 等函数式编程经验的朋友,会感觉 Rust的类型系统很容易理解,但是底层的内存管理和所有权机制又成了需要克服的学习障碍;来自C++编程圈的朋友,尤其是懂现代C++的朋友,对Rust所有权机制理解起来几乎没有困 难,但是类型系统和函数式编程范式可能会阻碍他们的学习。当然,如果正好你没有上述情况,那说明你的相关知识体系已经很全面了,你在Rust的学习之路上将会非常顺利。
这是不是意味着,在学习Rust之前需要把其他语言都学一遍呢?答案是否定的。
Rust编程语言虽然融合了很多其他语言的特性和范式,但它不是进行简单的内容堆叠,而是有机地融合了它们。也就是说,Rust遵循着高度的一致性内核来融合这些特性。我们只需要从Rust的设计哲学出发,牢牢地把握它的设计一致性,就可以把它的所有特性都串起来,从而达到掌握它的目的。
4、本书特点
- 从设计哲学出发,探索Rust 语言的内在一致性 。设计哲学是一门优秀编程语言保持语言一致性的关键所在。设计哲学是语言特性和语法要素设计的诱因和准则。理解Rust语言的设计哲学,有助于把握Rust语言的内核与一致性,把Rust看似纷繁复杂的特性都系统地串起来。
- 从源码分析入手,探索Rust地道的编程风格。Rust是一门自举的语言,也就是说,Rust语言由Rust自身实现。通过阅读Rust标准库和一些第三方库的源码,不仅可以深入理解Rust提供的数据类型和数据结构,更能体验和学习地道的Rust编程风格。
- 从工程角度着手,探索 Rust 对健壮性的支持。Rust 通过类型系统、断言、错误处理等机制保证内存安全的同时,还保证了系统的健壮性。从工程角度去看Rust,才能看到Rust对系统健壮性的支持是多么优雅。
- 从底层原理开始,探索Rust内存安全的本质。只有深入底层,才能理解Rust所有权机制对于内存安全的意义。而且可以进一步理解Rust的类型系统,以及Unsafe Rust存在的必要性。
5、如何阅读本书 ?
对于Rust初学者,建议按照章节顺序去阅读。因为本书每一章内容基本都依赖于前一章内容的前置知识。
对于Rust有一定了解的朋友,可以选择你感兴趣的章节去阅读。因为本书的每一章也是对一个垂直主题的深入探讨。
一些章节的开头罗列出了通用概念,这是为了更通透地讲解相关知识的来龙去脉。如果你对这部分内容不了解,那么建议你把这部分内容(属于前置知识)认真看完再去看后面的内容。如果你对这部分内容已经有了充分的了解,那么完全可以跳过,直接选择你最关心的内容去阅读。
6、章节概述
第 1 章 新时代的语言。这一章将从Rust语言的发展历史概述开始,引出Rust的设计哲学,通过设计哲学进一步阐述Rust的语言架构。该语言架构也是本书组织内容时遵循的准则之一。这一章还将介绍 Rust 语言社区的现状和未来展望。最重要的是,这一章将介绍 Rust代码的执行流程,这对于理解本书后面的章节会有所帮助。
第 2 章 语言精要。学习任何一门语言时,首先要做的就是了解其语法。这一章将罗列Rust语言中的常用语法,但不是简单罗列,而是遵循一定的逻辑进行罗列。在介绍语法之前,这一章会先对Rust语言的基本构成做整体概述。然后将介绍一个非常重要的概念:表达式。它是Rust语法遵循的最简单的准则之一。接下来才会依次介绍Rust中最常用的语法,让读者对Rust语言有一个初步的了解。
第 3 章 类型系统。类型系统是现代编程语言的重要支柱。这一章首先将以通用概念的形式介绍类型系统相关的概念,目的是帮助不了解类型系统的读者建立初步认知。接下来将从三方面阐述Rust的类型系统。为了理解Rust基于栈来管理资源的思想,有必要先了解Rust中对类型的分类,比如可确定大小类型、动态大小类型和零大小类型等。这一章还将介绍Rust类型推导功能及其不足。接下来将介绍Rust中的泛型编程。泛型是Rust类型系统中最重要的一个概念。最后会介绍Rust 的“灵魂”,trait 系统。对类型系统建立一定的认知,有利于学习后面的内容。
第 4 章 内存管理。这一章首先将介绍底层内存管理的通用概念。在此基础上,围绕内存安全这个核心,从变量定义到智能指针,逐渐阐述Rust中资源管理的哲学。这部分内容是真正理解Rust所有权机制的基础。
第 5 章 所有权系统。这一章首先会介绍关于值和引用语义的通用概念,然后在此基础上探讨Rust的所有权机制。读者将看到,Rust如何结合类型系统和底层内存管理机制,以及上层值和引用的语义形成现在的Rust所有权系统。然后,进一步围绕内存安全的核心,阐述借用检查和生命周期参数的意义。通过这一章的学习,读者将会对Rust的所有权系统有全面深入的了解。
第 6 章 函数、闭包和迭代器。在对Rust的类型系统和内存安全机制有了一定了解之后,我们将开始深入学习 Rust 编程最常用的语法结构。
- 函数是 Rust 中最常用的语法单元。Rust的函数承载了诸多函数式编程范式的特性,比如高阶函数、参数模式匹配等,同时也承载了面向对象范式的特性,比如为结构体及其实例实现方法,实际上就是一个函数调用的语法糖。
- 然后将介绍闭包的用法和特性,帮助读者对闭包建立全面深入的认知,更重要的是,通过学习闭包的实现原理,进一步了解Rust中零成本抽象的哲学思想。
- 最后介绍迭代器模式,以及Rust中的迭代器实现机制。迭代器也是Rust最常用的特性,通过这一章的学习,你将彻底了解迭代器。
第 7 章 结构化编程。这一章将对Rust混合范式编程进行探讨,会重点介绍Rust中的结构体和枚举体,以及它们如何在日常编程中以面向对象风格编程。同时,还将介绍三种设计模式,前两种是Rust标准库以及第三方库常用的设计模式,最后是一种合理利用Rust资源管理哲学的设计模式。通过学习这一章的内容,有利于掌握地道的Rust编程风格。
第 8 章 字符串与集合类型。
- 字符串是每门编程语言最基本的数据类型,Rust 自然也不例外。出于内存安全的考虑,Rust中的字符串被分为了多种,并且语言自身没有自带正则表达式引擎。这一章将从字符编码开始,围绕内存安全,对Rust中的字符和字符串做彻底梳理,并且阐述如何在没有正则表达式引擎的情况下,满足字符串进行匹配搜索等的需求。
- 集合类型也是编程中必不可少的数据结构。这一章将着重介绍动态数组Vector和Key-Value映射集HashMap 的使用,而且还会深入挖掘HashMap 底层的实现原理,介绍 Rust 标准库提供的HashMap安全性,进一步探讨如何用Rust实现一个生产级的数据结构。最后将通过探讨一个Rust安全漏洞的成因,来帮助读者正确理解容量的概念,从而写出更安全的代码。
第 9 章 构建健壮的程序。对于如何构建健壮的系统,Rust 给出了 非常工程化的解决方案。Rust将系统中的异常分为了多个层次,分别给出了对应的处理手段。在这一章,读者将学习Rust是如何以分层的错误处理解决方案来帮助开发者构建健壮系统的。
第 10 章 模块化编程。现代编程语言的一大特色就是可以方便地进行模块化,这样有利于系统的设计、维护和协作。Rust在模块化编程方面做得很好。这一章首先将介绍Rust强大的包管理系统Cargo。然后会以真实的代码实例阐述Rust的模块系统,并且将包含Rust 2018版本中模块系统的重大改进。最后将以一个完整的项目为例阐述如何使用Rust开发自己的crate。
第 11 章 安全并发。Rust从两方面支持并发编程。
- 首先,利用类型安全和内存安全的基础,解决了多线程并发安全中的痛点:数据竞争。 Rust可以在编译时发现多线程并发代码中的安全问题。
- 其次,Rust为了达成高性能服务器开发的目标,开始全面拥抱异步开发。这一章将从线程安全的通用概念开始,从Rust多线程并发讲到异步并发支持,带领读者逐步形成全面、深入、通透的理解。
第 12 章 元编程。元编程即程序生成程序的能力。Rust为开发者提供了多种元编程能力。
- 这一章将从反射开始介绍Rust中的元编程。虽然Rust的反射功能没有动态语言的那么强大,但是Rust提供了强大的宏系统。
- 这一章将从Rust的编译过程出发,带领读者深入理解Rust的宏系统 的工作机制,并且以具体的实例帮助读者理解编写宏的技巧。从声明宏到过程宏,再到编译器插件,以及第三方库syn和quote最新版的配合使用,都将在本章进行阐述。
第 13 章 超越安全的边界。前面的章节内容基本都是建立在Safe Rust的基础上的。而这一章将主要围绕Unsafe Rust的内容来构建,主要分为4大部分。
- 首先将介绍Unsafe Rust的基本语法和特性。
- 然后,围绕基于Unsafe进行安全抽象的核心,阐述Unsafe Rust开发过程中可能引起未定义行为的地方,以及相应的解决方案。
- 然后介绍 FFI,通过具体的实例来阐述Rust如何和其他语言交互,涉及C、C++、Ruby、Python、Node.js等语言,还将介绍相关的第三方库。
- 最后,将介绍未来互联网的核心技术 WebAssembly,以及 Rust 如何开发WebAssembly和相关的工具链。
相信通过这13章的内容,读者将会对Rust有全面、深入和系统的认识。
- 第1章 新时代的语言
- 第2章 Rust语言精要
- 第3章 类型系统
- 第4章 内存管理
- 第5章 所有权系统
- 第6章 函数、闭包与迭代器
- 第7章 结构化编程
- 第8章 字符串与集合类型
- 第9章 构建健壮的程序
- 第10章 模块化编程
- 第11章 安全并发
- 第12章 元编程
- 第13章 超越安全的边界