编程语言中的变革者 | 敢于打造理想世界的 Rust

2020-04-21 11:39:41 浏览数 (1)

在 2020 年 3 月 28 号,我为上海科技大学GeekPie社团 WorkShop#7「关于Rust你需要了解的…」 共享了一次分享,本文是该分享的文字版。内容比视频里的多了一些细节描述,但尽可能地精炼。

视频版见B站回放:https://www.bilibili.com/video/BV1ti4y1b7xy/ 三份 PPT 下载地址 : https://c-t.work/s/74b9dcf657be4d https://cowtransfer.com/s/c98f417a076d48 密码shanghaitech https://c-t.work/s/37a60fd0da9041 密码shanghaitech

另附加两篇关于「K-Rust :Rust 可执行形式语义」的论文:

上科大宋老师: https://arxiv.org/abs/1804.10806 Cyber Security Lab - NTU : https://arxiv.org/abs/1804.07608

~~~ 诞生篇 ~~~

今天给大家带来的主题是:编程语言中的变革者 | 敢于打造理想世界的 Rust 。

我今天想给大家分享的内容一共包含四部分:

  1. Rust 语言的诞生。任何一门技术的存在,它都是为了解决一个问题。那么 Rust 是为了解决什么问题而存在?这是我们面对Rust语言的时候,要必须要先搞清楚的一个问题。
  2. Rust 语言有什么特性。通过了解Rust语言的特性,来看看 Rust 语言如何解决它想解决的那些问题。
  3. 了解 Rust 在生产环境中有哪些应用。
  4. 对于当今大学生来说,学习 Rust 的意义何在?Rust 是如何让你成为一个更好的开发者?

我们先来了解一下,Rust 语言是如何诞生的。

Rust 语言到底想解决什么问题呢?这就要回顾一下计算机和编程语言发展历史了。

我们现在思考一个问题,假如没有 Rust 语言,时代的进程是什么样的?

在历史的早期,程序员们写代码,都是直接机器码编程,就是纸带机,大家都在那戳一个个小孔来编程。

随着计算机发展,直接打孔编程的方式已经满足不了需求了,效率太慢,于是有人发明了汇编语言。

汇编语言是对机器码的一一对应,可以直接翻译为机器码,汇编语言第一次提升了代码的可读性。这个重要性,不亚于生物进化史上,猿猴学会了直立行走。

随着时代的发展,又有人发明了 C 语言来替代汇编语言。但其实,真正的历史不是这么一蹴而就的,从汇编到C语言,是伴随着Unix系统的发展,经历了汇编、A语言、B语言才最终达成了C语言。C语言拥有强大的功能,高性能,且不依赖于具体机器系统的可移植性,帮助Unix顺利发展。

Unix 和C 语言就这么相辅相成的,发展至今,统治了世界。大家肯定都用过从Unix系统演化而来的Linux、BSD、MacOS等等。

后来,Bjarne博士在对Unix内核做分析的时候,发现没有合适的工具能有效分析内核分布而造成网络流量,以及怎样将内核模块化,于是他就考虑,是否应该发明一种新的语言。在当时如果想和C竞争,就必须错开和C的应用领域,并且同时拥有和C一样的性能。最后他基于C语言,并且从Simula汲取了类的概念,从Ada语言中取来了模板、名字空间和异常等,最终发明了Cpp语言,也就是 C with Class。

这在当时,Cpp的设计确实是非常先进的,并且在1995年之前在工业界非常流行。

但是当Java和C#出现之后,以及硬件价格开始大规模下降的时候,Cpp受到了一定的冲击。

其实在Java诞生前夜,Sun公司的人还在考虑使用C 来发明一种语言,但是他们发现,C 存在很大的问题,C 太复杂,以至于很多开发者在错误使用它。并且C 缺乏可移植安全性、分布式程序设计和多线程功能、垃圾回收等。因为他们想要一种易于移植到各种设备平台的语言。

一直到1994年,Sun公司的人改变了努力的目标,他们认为,随着网景公司Mosaic浏览器的到来,互联网将变得越来越流行,而这一远景是他们在有线电视网中看到的。于是Java诞生了。Java随着浏览器的发展而发展,但是后来受到微软的阻拦之后,IE里虽然没有了Java平台,但是Java此时已经普及到了服务端和手持设备上。JSP和其他Java技术也就流行了起来。

事实证明这个策略是相当正确的。

随着互联网的高速发展,一直到2004年,Ruby on Rails的出世,带动了硅谷互联网创业浪潮,这算是互联网的加速时代。

一直到2015年,互联网创业浪潮才退去。互联网流量到了前所未有的高度。为了提供更稳定和更好的服务,互联网逐渐进入了云原生时代。Docker的横空出世,让Go语言也开始普及了。

我们回顾了编程语言的发展历史,看的出来,基本上一些主流语言的诞生,都是随着时代的变化而出现。

好像没有Rust语言,这个时代也会继续发展下去,毫无影响。但其实我们要再仔细的推敲一下,就不难得出一些结论:

第一:C/Cpp 构建了整个互联网世界的基础。

其实当时还有更加安全的语言Ada,其实Ada的设计理念非常先进,包括了「编译期类型检查、确定性内存管理、内置安全并发模型,无数据竞争、泛型」等特性。但是为什么没有成为主流呢?这是当时那个性能为王的时代的必然结果。Unix的发展,性能是第一,但是安全并不是主要的,因为个人电脑并没有普及开。

所以,追求性能,牺牲了安全性,于是造就了一个不安全的世界。

第二、Java为了突破C/Cpp的桎梏,进一步引入了GC

Java诞生之时,正是互联网发展初期,个人电脑得到了一定程度的普及,安全性开始被注重了起来。但是Java是通过引入GC来解决内存安全的问题,把内存管理交给程序和算法,这个思路是对的,但是势必会牺牲一部分性能。

第三、摩尔定律导致硬件下降,互联网创业潮,各种动态语言流行,开发效率倍增

高速的发展,势必会积累很多技术债务,软件的工程性遭到了挑战。编程语言上手门槛变得越来越低,这个时期,只注重生产力,码农和码畜由此诞生。

第四、容器化推动了云原生的发展

创业浪潮虽然退去,但是流量激增,操作系统的瓶颈凸显。首先,需要最大化利用资源,容器比虚拟机更节省资源。其次,容器的沙盒化更容易进程间相互隔离,安全性增加。

时间到了2020年了,接下来我也想让大家和我一起思考一下,互联网下一步的发展方向该看重什么?

你能想到的,听到的,技术前沿名词都有哪些呢?

5G,万物互联,互联网走向物联网。

数字金融,数字货币、区块链正在逐渐走进我们的生活。

人工智能、自动驾驶、智能家居正在改变我们的生活。

世界的不确定性,更加促进了互联网的发展,一场疫情,老师都变成主播了,之前我们程序员最期待的远程办公,也突然实现了。

你会发现,各种软件和数字产品,正在侵入我们的日常生活。

然而,我们的互联网大厦却是漏洞百出。黑产盛行,网站被破解,隐私被卖,网络诈骗横行,数字货币被盗,智能门锁被破解,汽车被控制。安全,成为了当下,以及未来发展的重中之重。

我们的互联网世界,急需改变。表面上看似平静,实则暗流涌动。

有人的地方就有Bug,因为我们的大脑无法做到机器那样的精确思考,总会出现盲区。

但是不是就没有办法了呢?

非也,在2019年2月,微软安全响应中心的工程师在以色列举行的Bluehat会议上,发表过一篇演讲:《微软:70%的安全漏洞都是内存安全问题》。

我们不是要解决所有的Bug,也许未来人工智能有高度发展以后可能会做到?但现在我们能做的,就是尽可能地去消灭可以被消灭的问题。比如这个内存安全问题。

安全的世界,是需要付出代价创造出来的,而不是它自己来的。

至于我们要付出什么代价,先按下不表,我们接着往后面讲。

我们人类之所以能发展到现在,是因为总是存在一些有远见的非凡人物,为我们看清和指明方向。

在2006年,Mozilla雇员 Graydon Hore,意识到了我们刚才讲的那个问题:未来的互联网,一定会同时注重安全和性能。性能肯定是不断的追求。但是安全,才刚刚开始被注重。

Graydon 作为一名职业的编程语言,日常工作就是给其他语言开发编译器和工具集,久而久之,他其实早已萌生了自己开发一门编程语言的想法。

这门编程语言,必须要承载他对未来互联网世界的愿景。也就是,内存和性能兼备。

并且,他在日常和众多语言打交道的日子里,看到了很多非主流语言里也包含了优秀的特性,他不想让这些语言的优秀特性被埋没。

于是他就创造了 Rust 语言。

Rust 语言的主要目标是:

  1. 默认内存安全
  2. 媲美C/C 的性能
  3. 默认线程安全

Rust 语言的Logo就是右侧像齿轮一样的图案。

“Rust”这个名字包含了 GH 对这门语言的预期。在自然界有一种叫作锈菌(Rust Fungi)的真菌,这种真菌寄生于植物中,引发病害,而且号称“本世纪最可怕的生态病害”之一。这种真菌的生命力非常顽强,其在生命周期内可以产生多达 5 种孢子类型,这 5 种生命形态还可以相互转化,如果用软件术语来描述这种特性,那就是“鲁棒性超强”。可以回想一下 Rust 的 Logo 形状(如图 1-1 所示),Logo 上面有 5 个圆圈,也和锈菌这 5 种生命形态相对应,暗示了 Rust 语言的鲁棒性也超强。“Rust”也有“铁锈”的意思,暗合“裸金属”之意,代表了 Rust 的系统级编程语言属性,有直接操作底层硬件的能力。此外,“Rust”在字形组合上也糅合了“Trust”和“Robust”,暗示了“信任”与“鲁棒性”。

Rust 名字起的这么好,语言目标也非常令人激动,那么, Rust 是如何做到这个目标的呢?

~~~ 特性篇 ~~~

先来看一下 Rust和其他语言相比是什么样的。

首先,和 Python 为代表性的动态语言相比,Rust有以下优点:

  1. 性能更快
  2. 零成本抽象
  3. 更少的内存占用
  4. 真正的多线程支持
  5. 代数数据类型
  6. 模式匹配
  7. 静态类型
  8. 几乎不会在运行时崩溃

再和Java对比一下,优势在于:

  1. 无GC开销,性能更快
  2. 更少的内存占用
  3. 零成本抽象
  4. 不会抛出ConcurrentModification异常
  5. 支持模式匹配
  6. 拥有一致的构建系统和依赖管理,Java的则很多可选项

和C/C 相比,优势在于:

  1. 无段错误
  2. 无缓存区溢出
  3. 无空指针
  4. 无数据竞争
  5. 强大的类型安全的类型系统
  6. 拥有统一的构建系统和依赖管理

和 Go 语言相比,优势在于:

  1. 无GC 暂停
  2. 无空指针
  3. 更优雅的错误处理
  4. 安全并发
  5. 更健壮的类型系统
  6. 零成本抽象
  7. 统一的依赖管理

总的来说,Rust的特点可以归结为:

  1. 无GC 内存安全
  2. 默认线程安全,无数据竞争
  3. 零成本抽象能力
  4. 工程鲁棒性更强
  5. 性能媲美C/C
  6. 现代化语言特性,更易用
  7. 强调实用性
  8. 开源社区是语言的一部分

有的人可能会认为:不是编程语言的问题,而是写代码的人水平不够,才出现这种安全问题。

然而,没有程序员是全能的,Rust 编译器捕获的错误,有可能超出程序员的经验之外。难道开车上路,有更好的司机,就不需要安全带了吗?非也。这个世界变得越来越复杂,我们需要像 Rust 这样带有安全防护的语言来防止错误,保证程序的正确性。

大家可能会觉得 Rust 语言功能如此强大,它的设计是不是很复杂呢?

Rut其实没有那么复杂,首先它遵循有一套自己的设计哲学:

  1. 内存安全
  2. 零成本抽象
  3. 语言一致性
  4. 实用性

所以,Rust 语言的整体架构,必须遵循上述哲学。

但是Rust语言为了保持简洁,它采用了基于类型系统的语言架构。

在Rust中,一切皆类型。

在类型系统之上,包含了一层语义,即所有权语义,以及承载了两种编程范式,OOP和FP。

在类型系统之下,包含了一个半自动内存管理系统,来自于C 11 引入的RAII,基于栈来半自动管理堆。

Rust编译器会根据类型系统,在编译期进行各种安全检查、展开抽象等等。

这种语言架构,导致的结果就是:要求开发者对于Rust语言的心智模型,必须和编译器达成一致。如果不一致,那么开发的时候,就会遇到编译器的阻拦。

这就是我前面所说的,安全的代价。

开发者,必须要先学会 Rust,并且在写代码之前,做好类型设计,才能更高效地利用 Rust 产出正确的代码。

「一把梭」的时代,要一去不返了。

接下来,我们看一些代码来让大家感受一下 Rust 的特性。

Rust 引入了所有权语义来保证内存安全。

Rust 中使用 let 来声明一个绑定(变量),上面的 x 意味着它绑定了一块内存区域,它对这块内存区域有所有权。

第二行代表,x 将它的所有权交给了 y,这在 Rust 里面叫做「所有权转移」。

第三行,调用 drop 函数想释放 x 绑定的内存区域,但是 Rust 编译器不会让这行代码通过编译。

这是因为 ,Vec 是默认存储在堆内存。假设,如果不发生所有权转移的话,在栈内存上面,将出现同时指向 Vec 堆内存的两个指针,就会发生「双重释放」同一块内存区域的安全问题。

在C/Cpp中,处理这类问题,一般都是靠开发者本身的能力来决定,但是在 Rust 里,不管是什么水平的开发者,必须先通过编译器这一关。这就有效保证了程序的正确性。并且这一切都是在编译期完成的,而非运行时检查。

Rust 也通过编译期借用检查来保证不会出现悬垂指针的问题。

上面代码中,定义了 x 可变绑定(绑定默认不可变,此处通过 mut 修饰符显式指定为可变),它的值是 Vec 动态数组。

第二行,定义了 first 绑定,它的值是指向 x 数组第一位元素的引用。

然后第三行,将 x 的所有权转移给了 y。

在最后一行的打印语句中,想要对 first 进行解引用操作,但是这个时候 Rust 编译器会阻止代码通过编译。这是因为,first 是对 x 的引用,但是 x 的所有权已经被转移了,first 就自动失效。 如果 first 没有自动失效会发生什么呢?它可能会变成一个野指针。

Rust 中绑定默认不可变。上图代码中前两行会正常编译,但是最后一行就不能正常编译了。

这是因为,push 方法会自动对 v 进行可变借用,此处需要的是 &mut v,但是因为 v 是不可变绑定,所以此处无法进行可变借用,从而无法对数组进行 push 修改。

默认不可变,显式指定可变。可以帮助开发者在写代码的过程中,就想清楚状态如何改变,从而在代码设计层面一定程度上来保证正确性。

这段代码和上面的代码同理。显式的可变,会增强代码的可读性,提高代码的正确性。

Rust 默认线程安全。因为 Rust 的类型系统,可以通过 Send 和 Sync 这两个 trait 对类型进行鉴别,哪些类型是可以在线程间安全传递的,哪些不可以。

上面代码中的 Rc,就是非原子类型的,所以它没有被实现 Send 和 Sync,所以它不是线程安全的类型。在上面代码中,编译器不会让第三和第四行代码通过编译。

相反,Arc 则原子类型的,它实现了 Send 和 Sync,那么 Rust 编译器就能在编译期识别它是线程安全的类型。

而最后三行代码,则存在两个问题:

1. std::thread::spawn 是创建了一个子线程,并且在该线程中执行了闭包,该闭包中使用了 v.push 为数组中插入一个数字。试想一下,如果这行代码通过编译,会发生什么事情?主线程中最后会调用 pop 方法,但是因为线程间其实并不同步, pop出来的元素很可能不是 42 。这是线程不安全的代码。所以, Rust 编译器会阻止代码通过编译。Rust 编译器其实是通过所有权机制进行判断,v 此时被传入了闭包中,但是它是一个可变借用。因为子线程很可能比主线程运行时间长,当主线程这边执行完了代码, v 很可能会被销毁,但是闭包中还存有 v 的引用,那这就是一个悬垂指针,这是 Rust 决不能允许发生的事情。

2. v 是可变绑定, 在子线程中的闭包中,被可变借用了一次。但是在主线程尾部代码的 pop 方法,其实也会对 v 进行可变借用。在 Rust 中,可变借用是独占的,也就是说,不能同时对 v 进行两次或多次可变借用。否则,v 就会被修改出非预期的值。

看到了吗?Rust 的所有权机制,完美地在编译期发现了线程安全问题。

Rust 提倡的是显式处理的艺术。

在上面代码中,Option<T> 是一个枚举(enum)类型,这其实是一个代数数据类型中的「和(sum)类型」。

你可以用「加法原理」来简单地理解该类型,也就是说,完成一件任务,存在 A 或 B 等多种办法,选其中一种即可完成该任务。

同理,对于 Option<T> 类型,存在 Some(T) 和 None 两个值,前者代表「有」,后者代表「无」。也就是说, Option<T> 这个类型,代表一种「可选」类型。

所以,在倒数第三行代码中, find 方法返回的应该是一个 Option<T> 类型,因为在数组中搜索大于等于42的数,是有可能搜不到的。所以,这个结果会同时存在两个值,要么是有值,要么是没有值。所以,当你要使用 v 的时候,你要通过模式匹配(match)来判断,到底是 Some(T) 还是 None。这就强制了开发者去处理 None 的情况,有效避免了空指针。

上面 Result<T, E> 和 Option<T>,是相似的。只不过 Result 是用于错误处理,而 Option 用于消除失败。这也体现了 Rust 错误处理的一种精致的哲学,不像其他语言那样只用一个异常就包括了开发过程中的所有问题。在 Rust 里,你可以分情况用不同的类型来处理错误。

并且 Rust 通过引入代数数据类型,为开发者提供了优雅的错误处理方法。

Rust 也为开发者提供了底层内存分配的控制能力。

Rust 默认在栈上存储数据,但是你也可以通过 Box<T> 这样的智能指针显式地在堆上分配内存。

而且可以看具体的场景,选择适合你的全局内存分配器。

你可以通过泛型来静态分发,也能通过 trait 对象进行动态分发。

Rust 中零成本抽象的基础是 trait。

trait 是对 类型 行为的抽象。它有四个作用:

1. 作为接口。

2. 泛型限定。

3. 标签。比如 Copy 、 Size、Sync、Send等,其中 Copy trait,可以让编译器来识别哪些类型是可以安全存储到栈上的,哪些又必须是堆上,如果在堆上,就能自动Move所有权。

4. 抽象类型。

trait 是 Rust 的灵魂。trait 也是 Rust 对 组合优于继承 理念的一种体现。

Rust 提供了强大的元编程工具:宏。

因为 Rust 还在成长中,其 AST(抽象语法树)还在频繁地变化,所以 Rust 将 Token (分词)接口 稳定了出来,宏就基于 Token 处理。

Rust 现在支持声明宏和过程宏,用于满足不同的需求,目前过程宏还在不断地完善和优化,目前还在等程宏属性宏的稳定。

Rust 本质上可以分为「Safe Rust」和 「Unsafe Rust」。

这是因为,如前文所说,我们整个互联网的世界就是建立在一个 Unsafe 的基础上。我们必须拥抱 Unsafe,才能建立 Safe 的理想世界。

所谓 Safe,其实就是 编译器对你说:Trust me this time。

所谓 Unsafe,其实就是 你对编译器和其他开发者说:Trust me thist time。并且,也意味着,其他开发者对你说:trust you this time。

不需要对 Unsafe 感到恐惧。虽然现在 Unsafe Rust 还缺乏一些开发规范,但是 Rust 团队还在努力,将来也会通过 Miri 的形式,在Unsafe Rust 中加入 UB 自动检查,到时候 Unsafe Rust 将更加有保证。

Rust 中还提供了零开销的 FFI ,可以轻松通过 C-ABI 来访问任何函数,也可以通过 C-ABI 来公开 Rust 的函数和类型。

说到这里,Rust 的特性基本差不多了, Rust 还有很多特性等待你去探索。

~~~ 应用篇 ~~~

只有在了解 Rust的特性之后,才能选择合适的场景去应用它。

在了解Rust语言特性之后,第一印象是,Rust 语言是冲着C/C 的应用领域而去的。

但其实也不仅仅如此,因为 Rust 语言包含了很多现代语言特性,有高度抽象的表达能力,它其实也适合 Java、python、Andriod 、Swift的应用领域。

再加上现在 WebAssembly 的支持,Rust 也能应用于前端开发。

本质上, Rust是一个真正的全栈语言,适用于嵌入式、操作系统、网络服务、应用开发、游戏开发等等领域。

所以,有人把 Rust 称为是新时代的C语言。

因为C语言当时开创了一个互联网时代,那么 Rust 既然拥有C/C 的能力,是不是也可以开创一个新时代呢?

这个问题的答案,就仁者见仁,智者见智吧。

这里列出了一些相对比较知名的 Rust 实现的产品。

这些项目或产品,都有一个共同的特点:它们都使用了 Rust 来创造或应对未来。

比如,Goolge 的 Fuchsia 操作系统,它有大概近 50% 的代码是 Rust 实现的,主要用于网络层。为什么要重新写个操作系统?我们前面说过了,操作系统到了它的瓶颈,不管你有多么喜欢 Unix 的设计哲学,但是时代在变化。

包括 Redox,是纯 Rust 实现的下一代安全的操作系统,背后的商业公司是 System76 ,它的理念是「一切皆 URL」。

TockOS,则是纯 Rust 实现的嵌入式实时操作系统,最近已经用于 Google 的加密硬件设备产品中。

Bottlerocket 则是亚马逊纯 Rust 实现的基于 Linux 的专门承载容器的操作系统,专注于安全性和可维护性,提供可靠、一致的服务,以及基于容器的工作负载的安全平台。这是亚马逊多年云平台产品积累的经验,因为它们也看到未来安全和性能兼备的重要性。

国产分布式 New Sql 数据库 TiDB 的底层分布式存储 TiKV,也是 Rust 实现的。还有国产的区块链公链项目 NervOS,也是用 Rust 实现的。

还有很多优秀的项目,它们都使用了 Rust。此处就不一一列举了。

在 Rust 的官方页面( https://www.rust-lang.org/zh-CN/production/users )上,可以看到在生产环境中使用 Rust 的公司。上面只是列举了一部分,其中包括了国内的字节跳动(飞书)、PingCAP(TiKV)、秘猿(NervOS、Cita)三家公司,其实还有知乎、淘宝,也都在使用 Rust。将来大家一定也还会看到更多使用 Rust 的公司。

但是,当前 Rust 也存在一些缺点,阻碍了很多公司想要使用它的决策。

1. 学习曲线高?

这是流传最多的一个原因。Rust 的设计目标和特性,决定了 Rust 是一个进入高门槛的编程语言。但是这并不意味着 Rust 是一个复杂的语言。相反, Rust 是一门简洁的语言。Rust 语言的设计高度一致性,足以让开发者抓住它简洁的内核,建立和 Rust 编译器相匹配的心智(编程)模型。当然,这需要开发者,下一定的功夫。

2. Rust 编译慢。这同样是 Rust 语言设计目标引起的问题,因为 Rust 要在编译期完成各种安全检查、展开抽象等功能。幸运的是,Rust 官方团队也在逐渐改进这个问题。比如支持增量、并发编译等功能。

3. Rust 生态还在成长过程中。 比如最令人期待的异步开发功能,才稳定没多久,生态还在成长,这可能会给某些团队带来引入的困难。

4. 有些语言特性还待完善,比如 Const Genric 、特化等。

还有一点需要注意,Rust 并不是默认就是高性能的代码,还需要开发者自己优化。

~~~ 学习篇 ~~~

那么,当地大学生学习 Rust 有什么意义呢?难道学习C/Cpp/Java还不够吗?

Rust 和 C/ Cpp/ Java的比较前面已经说过了。我认为, 大学生学习 Rust 的意义有以下几点?

1. 跟进时代变革的脚步。学习 Rust 可以紧跟技术的前沿,了解相关领域的发展动态。

2. 无阻碍地培养自己的全栈能力。Rust 语言本身就有全栈能力,你掌握了 Rust 语言,就不用把自己束缚到某个领域中,因为 Rust 在操作系统、数据库、网络服务、嵌入式、前端开发等等,都有应用,你要切入某个领域,就不需要再多学一门编程语言了,只需要掌握那个领域的领域知识即可。

3. 打造良好的编程基础和思维习惯。Rust 是当下唯一一门,抽象表达能力比肩高级动态语言,性能和底层控制能力比肩C/C 的语言,学习 Rust 的过程中,会把你对于底层操作系统、网络、范式抽象、设计模式等基础都训练一遍。如果你不得不学其他语言,有了这些基础,你会很快掌握其他语言。并且,在 Rust 编译器的打磨下,你能拥有一个良好的思维习惯。

4. 成为更好的开发者。

为什么这么说呢?因为 Rust 编译器的存在,可以让你养成:

1. 养成先思考,再动手的编码习惯,避免一把梭。

2. 对内存安全、线程安全等基础建立一个系统的认知,可以高效地产出正确的程序。

对于企业来说,那你就是一个合格且更优秀的开发者。

~~~ 结语 ~~~

学习 Rust 让我重新爱上了编程,使用 Rust 让我感到骄傲和自豪。我也希望能把这门优秀的语言,推广给更多的人,尤其是高校的广大同学们。

0 人点赞