学习 Rust:从零开始
由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!
我决定是时候学习Rust 了,为了保持自己的动力,我将在这里记录我的学习进展。
简单介绍一下我自己:我是一名网页开发人员,从业大约五年,虽然之前也断断续续地接触过一些其他技术。我熟悉Perl和PHP,但日常工作主要使用 JavaScript/TypeScript,无论是通过NodeJS还是ReactJS。我想学习 Rust,并没有什么特别的原因,只是觉得学习新事物很有趣。
我首先想到的就是用谷歌搜索,learn rust结果找到了“那本书”。这本书是由 Rust 社区为新手(或者叫 Rustlings)编写的入门指南,旨在帮助他们“扎实掌握这门语言”。
在公共场所学习
我选择公开记录我的 Rust 学习历程,因为我相信公开学习的力量。通过分享我的成功经验、挑战和心得体会,我不仅能加深自己的理解,还能为其他走在类似道路上的人提供一些帮助。
我亲身感受到了这种方法的价值。欢迎读者提出反馈、指正和建议。虽然我知道公开学习并不适合所有人,但我个人从中受益匪浅,也希望能够启发其他人考虑这种方式。那么,让我们一起来学习吧。
第一课“入门”
本课分为三个部分:
- 安装
- 你好世界!
- 你好,货物!
安装
看到安装说明列出来我松了口气,之前还担心要查怎么安装 Rust 呢。我用的是 Windows 系统,但决定在 Linux 系统下学习 Rust,所以我会通过 WSL 使用 Ubuntu。
安装命令看起来很简单,它使用 curl 下载某些东西,然后通过 sh 管道传输,因此我们可以假设下载的内容是某种 bash 脚本。
curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf | sh
信不信由你,这就是我犯的第一个错误。我看到了那条Rust is installed now. Great!信息,然后就继续学习下一课了。如果我再往下读一点,就会发现我需要单独安装编译器。
Linux 用户通常应该根据其发行版的文档安装 GCC 或 Clang。例如,如果您使用的是 Ubuntu,则可以安装 build-essential 软件包。
不过这个问题很容易解决,我很快就恢复了正常。
sudo apt install build-essential
你好世界!
下一部分是开发者社区的经典内容,即备受喜爱的“Hello, World!”示例。
我在这里学到了一些小知识,函数是用fn关键字声明的,任何 Rust 应用程序的入口点都是文件main中的函数main.rs,标准的命名约定是使用下划线分隔函数名和文件名中的单词。
正是在这个阶段,我发现我没有安装编译器,我认为这才是像这样的简单章节的真正原因,以确保我们所有人都正确设置。
你好,货物!
上一节非常简单,这一节也很简单,但它向我们介绍了cargo,它是 Rust 的包管理器,作为一名 JS 开发人员,我首先想到的是 NPM。
Cargo 让我们能够做一些很棒的事情:
- 为我们的包装命名。
- 添加软件包依赖项。
- 只需一条命令即可运行我们的程序。
- 分别以调试模式和发布模式构建我们的程序。
- 检查我们的程序是否可以编译,而无需实际构建。
这个例子让我们用 Cargo 的方式来重现之前的Hello, World!例子。代码非常简单,几乎不值得展示,但还是贴在这里吧。
fn main() {
println!("Hello, world!");
}
第二课“猜谜游戏”
第二课没有小节,本课的目标是编写一个猜数字游戏,用户输入一个数字,我们将其与随机选择的数字进行比较,游戏继续进行,直到用户猜对为止。
我们虽然还没有做出什么突破性的成果,但从打印静态文本到动态获取用户输入并返回结果的进步,仍然令人欣慰。
VSCode
这时我意识到,在 VS Code 中修改代码nano并不是个好主意,我需要用 VS Code 打开项目。我添加了一些扩展,希望能让开发更轻松一些。这些扩展包括rust-analyzer、crates和Even Better TOML。你可以使用任何你喜欢的编辑器,我只是习惯用 VS Code。
制作游戏
我们来看游戏教程,它会引导我们使用货物来搭建项目,并很快向我们介绍一些新概念。
- 关键词
use。 - 可变变量。
- 错误处理。
- 货物单据。
关键词use
关键字use允许我们从其他库中引入代码。作为一名 Web 开发人员,我想把它和`import`进行比较。默认情况下,Rust 可以访问“标准”库中的一组项目,这被称为 prelude,但如果你想要访问其他任何内容,则必须使用 ` use.`。
在他们给出的示例中,我们use std::io;这样做可以访问io命名空间,但这感觉有点奇怪,因为我们已经可以访问std含义std::io,这也是可访问的。
可变变量
在 JavaScript 中,我们有不可变变量和可变变量的概念,分别用 `int`const和 ` letint`const表示,其中 `int` 是不可变的,而let`int` 不是。Rust 则略有不同,除非另有说明,否则所有变量都是不可变的,`variable` 关键字也总是 `int` let,至少就我目前所知是这样。
let mut var1 = String::new(); // mutable
let mut var2 = String::from("Test String"); // mutable
let var3 = 6; // immutable
这本书在这里告诉我们,它将在第 3 课中再次讨论可变性。
错误处理
我们了解到两种错误处理方式,.expect它们不会尝试任何恢复操作,而是在应用程序崩溃时发布一条消息match。
Match它接收Result一个函数的返回值,然后允许你根据该返回值调用另一个函数Result。在示例中,我们已知parse返回值要么是 `true` 要么是 ` Okfalse` Err,因此match我们可以定义一个函数来处理这两种情况。我假设,当我们开始处理更多样化的函数时,`match` 函数将能够处理所有Result类型。
货物单
这是我目前为止最喜欢 Rust 的部分,我知道它不应该这么令人兴奋,但我就是觉得很兴奋。当你运行命令时,cargo docCargo 会扫描你使用的所有代码,并生成帮助页面来解释函数及其用法。
目前还没有太多解释,但我希望这些文档是由代码中的注释生成的,即使情况并非如此,能够自我文档化的代码库也让我非常感兴趣。
偏离常规路线
至此,前两节课已经完成,我决定对猜谜游戏做一些修改。我把游戏循环提取到一个单独的函数中,并添加了解析失败的错误信息。
我不喜欢的一点是magic这条线。
let guess: u32 = match guess.trim().parse()
我不喜欢解析器似乎能神奇地自动识别目标类型的感觉。所以我阅读了 VSCode 中解析器的提示信息,了解了它的语法turbofish。我不知道大家是否不喜欢这种语法,还是这本书的作者认为它对初学者来说太复杂,但对我来说,这种语法清晰明了得多。我们告诉解析器我们想要什么类型,然后它let根据这个类型推断出来,而不是反过来。
let guess = match guess.trim().parse::<u32>()
以下是修改后的代码。
结束语
感谢您与我一同踏上这段旅程。我计划继续推出这个系列,直至完整解读这本书。如果您想持续关注,可以点击“关注”按钮,以便接收新文章的通知。
正如我之前所说,欢迎留下任何反馈意见。如果你也在公开学习,请在评论中留下你的系列课程链接,以便我查看。
非常感谢您的阅读。如果您想在 Dev 之外与我联系,这是我的Twitter和LinkedIn 账号,欢迎来打个招呼 😊。
文章来源:https://dev.to/link2twenty/learning-rust-a-clean-start-4eom


