如何通过调试Rust来学习Rust

253 阅读3分钟

如果你不使用工具链来更多地接触Rust,那么工具链有什么用呢?学习任何语言都需要阅读现有的代码和编写大量的样本程序。这是熟练掌握一门语言的好方法。然而,还有第三种方法:调试代码。

通过调试学习包括尝试编译一个预先写好的(有问题的)样本程序,了解编译器产生的错误,修正样本代码,然后重新编译。重复这个过程,直到代码成功编译和运行。

Rustlings是Rust团队的一个开源项目,它帮助你通过调试的过程学习Rust。它还沿途为你提供了很多提示。如果你是Rust的初学者,并且已经开始或完成了Rust书的阅读,那么Rustlings是理想的下一步。Rustlings帮助你应用你从书中所学到的知识,并转到更大的项目上工作。

安装rustlings

我使用(并推荐)Fedora机器来尝试rustlings,但任何Linux发行版都可以。要安装rustlings,你必须下载并运行其安装脚本。建议你以普通用户(非root)的身份进行,没有任何特殊权限。

记住,要想使用rustlings,你需要在你的系统上有Rust工具链。

一旦你准备好了,下载安装脚本。

$ curl -L https://raw.githubusercontent.com/rust-lang/rustlings/main/install.sh  > rustlings_install.sh
$ file rustlings_install.sh
rustlings_install.sh: Bourne-Again shell script, ASCII text executable

检查该脚本,了解它的作用。

$ less rustlings_install.sh

然后运行它进行安装。

$ bash rustlings_install.sh
[...]
Installing /home/tux/.cargo/bin/rustlings
Installed package `rustlings v4.8.0 (/home/tux/rustlings)` (executable `rustlings`)
All done!

运行'rustlings'开始。

Rustlings的练习

安装时为你提供了rustlings 命令。与--help 标志一起运行它,看看有哪些选项可用。

$ rustlings --help

安装脚本还克隆了rustlings的Git仓库,并安装了运行样本程序所需的所有依赖项。你可以在rustlings 下的练习目录中查看这些样本程序。

$ cd rustlings
$ pwd
/home/tux/rustlings
$ ls
AUTHORS.md  Cargo.toml        CONTRIBUTING.md  info.toml install.sh README.md  target Cargo.lock  CHANGELOG.md  exercises install.ps1  LICENSE src tests
$ ls -m exercises/
advanced_errors, clippy, collections, conversions, enums, error_handling, functions, generics, if, intro, macros, mod.rs, 
modules, move_semantics, option, primitive_types, quiz1.rs, quiz2.rs, quiz3.rs, quiz4.rs, README.md, 
standard_library_types, strings, structs, tests, threads, traits, variables

从命令行列出所有练习

rustlings 命令为你提供了list 命令,显示每个样本程序、其完整路径和状态(默认为待定。)

$ rustlings list
Name         Path                                 Status
intro1       exercises/intro/intro1.rs            Pending
intro2       exercises/intro/intro2.rs            Pending
variables1   exercises/variables/variables1.rs    Pending
variables2   exercises/variables/variables2.rs    Pending
variables3   exercises/variables/variables3.rs    Pending
[...]

在输出的最后,你会得到一个进度报告,这样你就可以跟踪你的工作。

Progress: You completed 0 / 84 exercises (0.00 %).

查看样本程序

rustings list 命令显示了哪些程序是可用的,所以在任何时候你都可以通过将完整的路径复制到终端作为catless命令的参数来查看这些程序的代码。

$ cat exercises/intro/intro1.rs

验证你的程序

现在你可以开始对程序进行调试了。你可以用verify 命令来做。注意,rustlings选择了列表中的第一个程序(intro1.rs ),试图编译它,并且成功了。

$ rustlings verify
Progress: [-----------------------------------] 0/84
✅ Successfully ran exercises/intro/intro1.rs!

You can keep working on this exercise,
or jump into the next one by removing the `I AM NOT DONE` comment:

 6 |  // Execute the command `rustlings hint intro1` for a hint.
 7 |  
 8 |  // I AM NOT DONE
 9 |

正如你从输出中看到的那样,尽管样本代码已经编译,但仍有工作要做。每个样本程序在其源文件中都有以下注释。

$ grep "NOT DONE" exercises/intro/intro1.rs
// I AM NOT DONE

尽管第一个程序的编译工作很顺利,但在你删除I AM NOT DONE 注释之前,rustlings不会转到下一个程序。

编程和开发

移动到下一个练习

一旦你删除了intro1.rs 的注释,你就可以通过再次运行rustlings verify 命令转到下一个练习。这一次,你可能会注意到rustlings试图编译系列中的下一个程序(intro2.rs ),但遇到了一个错误。你要调试这个问题,解决它,然后继续前进。这是一个关键的步骤,让你了解为什么Rust说一个程序有bug。

$ rustlings verify
Progress: [>------------------------] 1/84
⚠️  Compiling of exercises/intro/intro2.rs failed! Please try again. Here's the output:
error: 1 positional argument in format string, but no arguments were given
 --> exercises/intro/intro2.rs:8:21
  |
8 |         println!("Hello {}!");
  |                         ^^

error: aborting due to previous error

获得提示

Rustlings有一个方便的hint 参数,它准确地告诉你样本程序有什么问题,以及如何修复它。你可以把它看作是一个附加的帮助选项,除了编译器错误信息告诉你的内容之外。

$ rustlings hint intro2
Add an argument after the format string.

根据上述提示,修复程序很容易。你所需要做的就是在println 语句中增加一个额外的参数。这个diff应该可以帮助你理解这些变化。

< println!("Hello {}!", "world");
---
> println!("Hello {}!");

一旦你做了这个改动,并从源代码中删除了NOT DONE 的注释,你就可以再次运行rustlings verify 来编译和运行代码。

$ rustlings verify
Progress: [>-------------------------------------] 1/84
✅ Successfully ran exercises/intro/intro2.rs!

追踪进度

你不可能在一天内完成所有的练习,而且很容易失去对你离开的地方的追踪。你可以运行list 命令来查看你的工作状态。

$ rustlings list
Name         Path                                  Status
intro1       exercises/intro/intro1.rs             Done   
intro2       exercises/intro/intro2.rs             Done   
variables1   exercises/variables/variables1.rs     Pending
variables2   exercises/variables/variables2.rs     Pending
variables3   exercises/variables/variables3.rs     Pending
[...]

运行特定的练习

如果你不想从头开始,跳过一些练习,罗斯特林斯允许你使用rustlings run 命令专注于特定练习。这样就可以运行一个特定的程序,而不需要对前一课进行验证。比如说。

$ rustlings run intro2
Hello world!
✅ Successfully ran exercises/intro/intro2.rs
$ rustlings run variables1

输入练习名称会变得很乏味,但rustlings为你提供了一个方便的next 命令,这样你就可以转到该系列的下一个练习。

$ rustlings run next

替代的观察命令

如果你不想在每次修改后不断输入verify ,你可以在终端窗口运行watch 命令,然后不断修改源代码来修复问题。watch 命令会检测到这些修改,并不断地重新编译程序,以查看问题是否得到了修复。

$ rustlings watch

通过调试来学习

众所周知,Rust编译器会提供非常有意义的错误信息,这有助于你理解代码中的问题。这通常会导致更快的调试。Rustlings是练习Rust的好方法,可以让你习惯于阅读错误信息,并理解Rust语言。在GitHub上查看Rustlings 5.0.0的最新功能。