我用 Rust 编程的这两年
摘要:近年来,Rust 被越来越多大厂投入使用,如微软的 VS Code、Visual Studio 等工具已提供对 Rust 的良好支持,Google 也宣布 Android 支持 Rust 语言来开发操作系统,Linux 内核也有意引入 Rust 代码等等。那么,对于个人开发者来说,用 Rust 编程又有什么不同呢?
链接:https://n-eq.github.io/blog/2022/11/01/rust-fiddling-2-years
声明:本文为 CSDN 翻译,未经允许禁止转载。
时间过得真快,距离我第一次接触 Rust,已经过去差不多两年了。我想通过本文反思一下这段旅程中一些令我印象深刻的事情和一些经验教训。
下面是我第一次提交 Rust 代码的截图。虽然时间可以追溯到 2021 年 1 月,但实际上在这之前,我已经在这段代码上折腾好几个星期了。
第一次接触 Rust
2020 年 12 月,我找到了一份新工作,但在这之前我早就对 Rust 有所耳闻。以前,我从事的是嵌入式开发,在我看来 Rust 是一门很强大的现代语言,最终有可能发展成为堪比 C/C++ 的主流语言。我感觉不认真学习 Rust 就有可能错过一个新时代。
初印象
首先申明,我没有正式地学习过 Rust,只是通过实践、阅读代码和文档自学。回想起来,我认为这不是一个很好的学习方法,我坚信花一些时间来学习官方提供的资料,快速理解语言及其设计理念和生态系统,这些都是必须的。接下来,才能用 Rust 编写一些严肃的项目。
Rust 的学习曲线很陡峭
我记得,Rust 宣称其最大优势是强类型语言,能够在编译期间跟踪对象的生命周期以及所有引用的变量范围,因此能够防止内存安全错误。
思路看似非常简单,但实际上使用静态变量和 RC 处理多个 crate 简直就是一场噩梦。对我来说,理解这个新概念极其有难度,而绕过该概念的最容易的方法就是不断克隆变量,但这不仅是错误的做法,尤其是在处理大型数据结构时,而且还会在你终于理解该概念之后带来很多麻烦。
幸运的是,编译器提供了很多提示和指向文档的连接,我必须说这真的很有帮助。
编译器不是正规的验证工具
这是一个很常见的误解,最近我与一位同事探讨 Rust,他认为 Rust 程序不可能会因为运行时越界而崩溃。然而不幸的是,Rust 编译器不是可以医治百病的灵丹妙药,有些程序虽然编译成功,但运行时还是会出问题。下面,举一个最常见的 Rust 数据结构的示例:
let mut v = vec![];
v.push(0);
v.clear();
let _ = v[0]; // panics
下面这段代码更狡猾:
let mut v = Vec::new();
#[cfg(target_os = "windows")]
v.push("a");
let _ = v[0]; // panics
在编译时检测越界访问需要对代码进行深度分析,会极大地降低编译速度(在我看来 Rust 的编译已经很慢了)。
Rust可能无法预测
我们团队最近发现了一个问题,我们的某个 crate(依赖)在生产环境下会在特定条件时崩溃。长话短说,如果使用了特定版本的 reqwest,且使用了其 rustls-tls-native-roots 特性,那么在系统证书不正确时就会崩溃。
我对此很惊讶,因为照此看来使用依赖是有风险的。即使现在的绝大部分 crate 都是开源的,人们也不太可能审查所有代码,更不用说评判使用时的风险了。绝大部分 crate 的文档都很差,这也印证了这一观点。如果能有一个像树一样分析项目依赖的工具,并给出所有容易崩溃的 crate 的鸟瞰图就好了。
解决该问题的方法是重载 Rust 的 panic_handler, 但这种方法只有在 #![no_std] 的项目中才能使用。
程序的可执行文件可能非常大
说起嵌入式的 no_std 非常有意思。我并没有在内存受限环境和低端设备上编写 Rust 程序的经历。尽管现在这不是个问题,但我还是要说,Rust 的可执行文件太大了。
我读过一些这方面的文章,其中一些给出了很好的观点。但我认为,Rust 想在内存受限环境下取代 C,还有很长一段路要走。在 #![no_std] 的世界中,我相信 Rust 仍然需要找到一种方法,来提供多种不依赖于默认的格式化函数的崩溃处理库,因为默认的格式化函数非常消耗内存。
Rust 工具的可互换性非常好
这一点也让我很惊讶,但这是一个好消息。
我从事的某个项目中包含大约 90 万行 C 语言代码,负责与 Rust 接口。有了 Rust,实现这一点并没有太大困难,甚至十分简单,而且许许多多 crate 和示 例也能证实这一点。通过 FFI 机制,编写其他语言代码的 Rust 绑定非常容易。我不敢说其他语言,但至少对 C 家族(C/C++/Objective-C)的支持非常好。
这并不是说完全不用做任何工作,因为你仍然需要写一些代码,将各个部分“粘”在一起,但这是必须付出的代价,而且我觉得这代价非常低。此外,我很高兴看到 Rust 坚持了自己的理念,要求使用者将低级代码定义为“不安全”(基本上,所有的 FFI 函数事实上都是不安全的,因为 Rust 对其他语言编写的代码没有任何控制权)。
Rust 很强大
我想用正面的评价来结束这篇文章。Rust 是一个非常丰富的语言,它在系统编程方面拥有巨大的潜力。限制所有权和借出机制能保证数据访问的安全性和高效率。更现代的语法和设计,使其更容易理解,而且也更容易使用多种编程语言模式和最新的范式。更不用说,Rust 的并行支持非常好,进程可以很容易地并行运行,不需要考虑竞争条件以及类似的问题。
结束语
我很喜欢使用 Rust。如果我有机会选择一门开发语言,那一定会毫不犹豫地选择 Rust。我看到了 Rust 的巨大潜力,希望它在未来能在嵌入式系统中大放异彩。最近出现的 Rust Linux 内核模块让我们看到了光明的前景。
《》全面上市,对话世界级大师,报道中国IT行业创新创造!