likes
comments
collection
share

在调试中学习 Rust

作者站长头像
站长
· 阅读数 3

以下内容为本人的学习笔记,如需要转载,请声明原文链接 微信公众号「ENG八戒」mp.weixin.qq.com/s/EFd0bEZmf… 在调试中学习 Rust

Rustlings 是 Rust 团队推出的一个开源项目,旨在帮助初学者在调试程序过程中学习 Rust 语言。

上期有篇文章讲到如何配置和升级 Rust 的工具链 《简明快速配置 Rust 工具链》,有兴趣可以点击查阅。工具链是用来编译调试程序代码的,如果你不上手去练习使用,那么这些工具将毫无用处。

学习一门计算机语言除了比较直白的方法是阅读别人优秀的代码和亲自上手编写大量的代码,还有就是实践中得真知。这篇文章的本意是侧重于实践,并介绍通过调试代码来学习。

具体点,准备一些现成的工程代码(也可以是你自己的代码),但这些代码或多或少存在一些错误,需要同学们自己在编译过程阅读编译器输出的错误信息和修复建议,并手动修复工程代码中蕴含的错误,然后再次编译,如此重复,直到工程能够完整编译结束和顺利运行。

恰好,Rust 团队提供了一个开源项目 Rustlings,就是为了契合这种学习思路,以帮助各位初学者顺利入门 Rust 语言。

下面开始我们的初体验吧!

安装 Rustlings

由于 Rustlings 依赖于 rust 工具链的应用,所以在安装 Rustlings 之前,你需要确保你所用的系统已经准备好 rust 的工具链环境。如果还没有,可以参考我的文章《简明快速配置 Rust 工具链》。

官方推荐的安装方式是通过下载它的安装脚本,然后在本地执行该脚本,该脚本会自动下载所有依赖包并编译安装,最终会安装好最新版 Rustlings。

下载安装脚本

$ cd ~
$ 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

如果上面在执行 curl 下载脚本文件时老是提示连接失败,估计是被墙了,可以在公众号回复关键词【rustlings_install】获取我的网盘备份。

运行安装脚本

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

安装脚本会克隆 rusdlings Git 存储库,并安装运行示例程序所需的所有依赖项。

好了,现在 rustlings 已经在你的环境里安装完毕。

动起手来

一切从 rustlings 指令开始,输入指令 rustlings 看看

$ rustlings

       welcome to...
                 _   _ _
  _ __ _   _ ___| |_| (_)_ __   __ _ ___
 | '__| | | / __| __| | | '_ \ / _` / __|
 | |  | |_| \__ \ |_| | | | | | (_| \__ \
 |_|   \__,_|___/\__|_|_|_| |_|\__, |___/
                               |___/

/Users/user/.cargo/bin/rustlings must be run from the rustlings directory
Try `cd rustlings/`!

显示末尾有个提示信息,意思是说 rustlings 指令应该在 rustlings 目录下执行

$ ll
total 8
drwxrwxrwx 1 user user  512 Sep 26 01:49 ./
drwxrwxrwx 1 user user  512 Sep 26 01:02 ../
drwxrwxrwx 1 user user  512 Sep 26 01:51 rustlings/
-rwxrwxrwx 1 user user 4662 Sep 26 01:15 rustlings_install.sh*
$ cd rustlings/
$ rustlings

       welcome to...
                 _   _ _
  _ __ _   _ ___| |_| (_)_ __   __ _ ___
 | '__| | | / __| __| | | '_ \ / _` / __|
 | |  | |_| \__ \ |_| | | | | | (_| \__ \
 |_|   \__,_|___/\__|_|_|_| |_|\__, |___/
                               |___/

Thanks for installing Rustlings!
...

不要惊慌!Rustlings 就是面向初学者的,它将通过一系列的调试实践,来教会你如何使用 rust 编写代码。

  1. Rustlings 的核心理念就是让使用者从实践中掌握学习内容,而不是停留在死记硬背语法和教条主义中。所谓的实践就是,提供一系列带有错误的练习代码片段,每个练习对应一个样例程序,问题可能是语法层面的,也可能是逻辑方面的,要求使用者从中发现问题并修正代码,以到达正常编译和测试运行。
  2. 官方推荐直接使用 watch 模式,在 watch 模式下,系统会自动开始第一个练习。所以,不要对弹出的错误信息感到惊慌,它只是提醒你---调试练习开始了。
  3. 假如在解决问题的过程中,发现需要帮助的时候,系统可以提供帮助信息。如果你正在 watch 模式下,请输入 hint 获得帮助信息,否则请直接执行 rustlings hint exercise_name 命令,exercise_name 就是当前你需要获取帮助信息的练习名。
  4. 当然,你如果发现有些问题不适合被公示出来讨论,那么你可以向 rustlings 的 github 仓库提交内容,链接如下 github.com/rust-lang/r…
  5. 在 rustlings 里同样可以使用代码补全功能,输入 rustlings lsp 命令即可。

列出所有练习

在 rustlings 安装目录下有个专门目录,用于存放练习示例程序

$ pwd
/home/user/rustlings
$ 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 也提供了命令直接显示所有的练习、各个练习的安装路径和状态

$ 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 / 96 exercises (0.0 %).

各个练习默认状态为待确认(Pending)状态。

在 rustlings list 命令返回的所有信息结尾处,有一份简短的练习进度报告,这样你可以据此跟踪自己的学习进度。

Progress: You completed 0 / 96 exercises (0.0 %).

聪明的你已经想到了,你可以用这条命令来帮你回忆上次练习到哪一步了。

上面这份报告显示我还是比较懒的,全部 96 个练习完全没动静,So ....

查看练习代码

既然已经知道练习的程序存放在哪里,那么就可以随时通过完整路径查看这些练习程序的代码。

一般我习惯用 vscode 编辑和阅读代码,所以我推荐先导航到代码目录,然后用 vscode 打开当前目录。如果你是在 Windows 环境下,可以鼠标右键直接打开,或者 Linux 环境下,可以在终端里输入以下命令

$ code ./

开始调试

rustlings 提供了推荐的练习顺序,第一步可以输入 rustlings verify,自动开始按照推荐的顺序验证下一个待确认的练习程序,包括先编译然后运行,同时输出结果。

开始的时候,可以不做任何修改,直接执行自动验证

$ rustlings verify
Progress: [---------...---------] 0/96 (0.0 %)                                 
✅ Successfully ran exercises/intro/intro1.rs!

🎉 🎉  The code is compiling! 🎉 🎉

Output:
====================
Hello and
       welcome to...                      
                 _   _ _                  
  _ __ _   _ ___| |_| (_)_ __   __ _ ___  
 | '__| | | / __| __| | | '_ \ / _` / __| 
 | |  | |_| \__ \ |_| | | | | | (_| \__ \ 
 |_|   \__,_|___/\__|_|_|_| |_|\__, |___/ 
                               |___/     
......

看到上面的输出之后,你会发现系统推荐的练习顺序其实就是 rustlings list 输出的顺序,而这里由于所有练习都是待确认状态,所以从第一个开始,就是 exercises/intro/intro1.rs,编译和运行过程没有报告任何错误。

但是你还是可以动手尝试修改,看看输出会怎样变化,然后再次运行 rustlings verify,虽然输出结果都是正确的,但还是停留在第一个练习的例子。

那么如何开始下一个练习并结束当前的练习呢?

进行下一个练习

Rustlings 系统会在开始验证之前,先遍历检索所有的练习程序源代码中的这行注释内容

// I AM NOT DONE

如果某个练习程序源代码中的这行注释内容是存在的,则认为该练习程序未完成,即使该练习程序代码能成功编译通过并运行。所以,在你确认完成某个练习后,务必删除 I AM NOT DONE,再继续下一个练习,这样执行指令 rustlings verify 才会开始下一个练习。

$ rustlings verify
Progress: [---------...---------] 0/96 (0.0 %)                                 
Progress: [---------...---------] 1/96 (1.0 %)                                 
⚠️  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:11:21
   |
11 |     println!("Hello {}!");
   |                     ^^

error: aborting due to previous error

删除 I AM NOT DONE 后,再次执行 rustlings verify 就直接开始了下一个练习。

从上面的输出来看,intro2.rs 编译过程出了问题,应该是语法层面的问题。这个报错信息还是很到位的,它的意思是 println! 的格式字符串里用了 1 个占位符 {} ,但是后边没有提供参数,需要补充参数,可以直接动手修复源码的问题。

如果这些练习的代码中碰到比较棘手的问题,而且编译器报错信息没有直指弊端呢?有没有更具体的修改建议?往下看!

获取提示

Rustlings 提供了 hint 命令可以获取更加准确的问题描述和修复建议。

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

可以看到这样的提示信息明显更有针对性,但这个提示命令 hint 仅能应用于 rustlings 提供的练习源代码上。

尝试修复一下 intro2 的问题

fn main() {
    println!("Hello {}!", "world");
}

再次运行验证

$ rustlings verify
Progress: [---------...---------] 0/96 (0.0 %)                                 
Progress: [---------...---------] 1/96 (1.0 %)                                 
✅ Successfully ran exercises/intro/intro2.rs!

🎉 🎉  The code is compiling! 🎉 🎉

Output:
====================
Hello world!

====================

指定练习

突然间,你可能发现有些练习就是想提前练练手,那么可以使用 rustlings run 命令跳过推荐顺序,然后专门对某个练习程序执行验证。

这里尝试对 exercises/tests/tests1.rs 执行验证

$ rustlings run tests1
⚠️  Compiling of exercises/tests/tests1.rs failed! Please try again. Here's the output:
error: macro requires a boolean expression as an argument
  --> exercises/tests/tests1.rs:19:9
   |
19 |         assert!();
   |         ^^^^^^^^^ boolean expression required

error: aborting due to previous error

tests1 源码的目标是对函数 you_can_assert 执行测试,但是编译器报错提示函数 you_can_assert 在调用宏 assert! 时没有提供参数,修复建议是在宏 assert! 后边添加布尔表达式作为参数,这里填充简单的真值 true 试试。

#[cfg(test)]
mod tests {
    #[test]
    fn you_can_assert() {
        assert!(true);
    }
}

再次执行 rustlings run tests1,没有任何的输出,表示测试程序没有捕捉到任何异常,测试正常结束,验证也通过。

如果在宏 assert! 后边添加假值 false 呢?

$ rustlings run tests1
⚠️  Testing of exercises/tests/tests1.rs failed! Please try again. Here's the output:

running 1 test
test tests::you_can_assert ... FAILED

successes:

successes:

failures:

---- tests::you_can_assert stdout ----
thread 'tests::you_can_assert' panicked at 'assertion failed: false', exercises/tests/tests1.rs:19:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace


failures:
    tests::you_can_assert

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

从上面的输出来看,测试程序捕捉到了异常,并结束测试流程,然后输出测试结果汇总。

快捷方式

每次启动练习都需要输入练习程序名称实在是太啰嗦了,rustlings 为你提供了一个快捷的 next 命令,使用它可以按照系统推荐顺序直接开始下一个练习

$ rustlings run next

自动检测改动

还记得上面提过 watch 模式吧?这个 watch 模式有什么妙用吗?

它就是用来监测练习对应的源代码是否有改动,如果有改动就立刻执行验证,相当于自动执行了 rustlings verify。起码,不用每次需要重新验证时,都要手动敲一次命令了,真的是妙。

怎么进入 watch 模式?

$ rustlings watch

更多

Rustlings 也提供了帮助命令,查看有哪些选项可用,和详细介绍

$ rustlings --help

认知从实践中来

从上面看来,Rust 编译器在处理源码后,会输出非常有意义的错误提示,这对开发者理解代码中的语法错误颇有裨益,而且会提高调试效率。

对于初学者来说,没有最好,只有更好。所以,有好事者就开发了 Rustlings 这个项目,在系统中专门利用调试过程以及一系列的工具帮助 Rust 初学者练习调试。

Rustlings 是练习 Rust 调试、理解 Rust 语法的一个非常好用的系统。希望上面的内容对你有帮助!