INTERACTIVE LAB

rust2 个可运行示例1 次浏览

Rust 环境准备与初始

安装 Rust 工具链、用 Cargo 创建第一个项目,并跑通 Hello World;文中配有可编辑运行的代码实验。

前言

Rust 是一门非常有意思的语言,初学时觉得它别扭无比,熟练之后又想用它重构一切。

相比于 C/C++,Rust 同样适合底层开发。它不能简单地替代 C/C++,但在网络服务、命令行工具、嵌入式和高性能应用等场景中,确实是一个很值得考虑的选择。

当然,越是涉及底层,需要控制的细节就越多。Rust 虽然有安全可靠的内存模型和便利的包管理,但学习曲线依然不算平缓。

目前来看,Rust 的生态已经比较成熟,但不同方向的发展程度仍然不一样。

比如 GUI 方向目前还没有一个由官方主导、能够覆盖所有场景的统一框架,因此选型时需要多花一些时间。

但这并非无法解决。Rust 可以通过 FFI 调用 C 语言库,相关内容可以参考后文:Rust 与 C/C++ 互操作实战指南。

这意味着许多 C 库都可以通过绑定在 Rust 中使用;而C++ 库则通常需要额外的封装,不能简单理解为“拿来就能调用”。

例如可以使用 Rust 绑定的 FLTK、GTK,也可以了解 egui、iced、Tauri 等 Rust 生态中的方案。

如果你熟悉 Web 前端,也可以了解 Tauri:Tauri。

Rust 带来的代码安全和工程便利确实很有吸引力,但它和 C/C++ 仍会长期共存,具体选择要看项目的历史包袱、平台支持和团队经验。Windows、Linux、macOS 以及大量基础设施都积累了庞大的 C/C++ 代码,短时间内不可能全部替换。

同时需要注意:有 C/C++ 经验会更容易理解指针、栈和堆,但学习 Rust 并不要求必须先学过 C/C++。

对于刚刚入门编程的同学,先掌握变量、函数和命令行等基本概念,再学习 Rust 会更顺利:初识 C++。

Rust 简介

Rust 由 Graydon Hoare 在 2006 年开始作为个人项目开发,Mozilla 从 2009 年开始参与赞助。

第一个有版本号的 Rust 编译器于 2012 年 1 月发布。Rust 1.0 作为第一个稳定版本于 2015 年 5 月 15 日发布。

Rust 1.0 在 2015 年发布,到现在已经有了比较成熟的工具链和生态。网络服务、命令行工具和 WebAssembly 等方向发展得比较快,GUI 和部分嵌入式场景则仍然需要自己做好技术选型。

简单了解 Rust 的发展情况后,再来看看它为什么受到关注。相比于 C/C++,Rust 能为开发人员带来不少便利:

  • 内存安全:

在 safe Rust 中,编译器会检查所有权、借用和生命周期,能够在编译阶段阻止空指针、悬垂指针和数据竞争问题。

rust也允许你写unsafe的代码,以维持对数据的完全掌控,但这也意味着各类C/C++中的问题也会随之出现、因此除非必要、一般不建议在rust中写unsafe代码。

相比之下,C/C++ 中的指针和内存问题通常需要开发者自己维护,尤其是在大型项目中,很容易因此产生各种 Bug。

  • 高效性能:

Rust 具有与 C 和 C++ 相当的性能,同时提供了闭包和模式匹配等现代语言特性。这使得 Rust 很适合编写高性能、低延迟的系统级应用程序和库。

  • 并发性:

Rust 的所有权系统和借用规则,可以在编译阶段发现一部分线程安全问题。它不会自动替你设计并发程序,但能让错误更早暴露出来。

  • 社区支持:

Rust拥有活跃的社区,在crates上提供了许多开源库、工具和框架,可以大幅度提升开发效率。

C/C++ 同样拥有庞大的社区和成熟生态,只是不同库之间的构建方式和包管理方式不够统一。

  • 统一包管理

C/C++ 中,使用第三方库时经常需要自己处理下载、安装和配置。

Rust 通过 Cargo 统一处理项目构建、依赖解析、测试和文档生成。它不能解决所有问题,某些库仍然需要系统组件或 C 编译器,但日常使用确实方便很多。

虽然目前也有 vcpkg 等不错的 C/C++ 包管理工具,但不同项目的使用方式仍然不完全统一。了解这个区别后,接下来直接动手创建一个项目,感受一下 Cargo 的工作方式。

安装 Rust 工具链

与 C/C++ 一样,Rust 也是一门编译型语言。Rust 源代码通常需要先编译成二进制程序,然后才能运行。Windows 系统中常见的 .exe 就是一种可执行程序,Linux 和 macOS 下的文件名和扩展名则不一定相同。

建议直接从 Rust 官网进入安装页面:Rust

Rust 官方推荐使用 rustup 管理工具链,而不是只安装一个固定版本的编译器:

image.png

Windows 用户可以下载 rustup-init.exe;如果使用 Linux 或 macOS,则按照官网提供的命令安装即可:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

如果使用 Windows,下载后运行安装程序,等待安装完成即可。如果没有安装 Visual Studio,还需要安装 Microsoft C++ Build Tools 和 Windows SDK。

安装完成后,重新打开终端,运行下面几个命令:

rustc --version
cargo --version
rustup show

能正常打印版本信息,就说明工具链已经安装成功了。如果不知道如何打开或进入控制台,可以参考文章:程序员必懂的常识

第一次使用可能会觉得有些疑惑:明明安装的是 Rust,这里怎么一直在使用 Cargo 命令呢?

简单来说,Rust 工具链中有几个经常遇到的命令:

  • rustc 是 Rust 编译器;
  • rustup 用来安装和管理 Rust 工具链;
  • cargo 是构建工具和包管理器。

后面开发 Rust 项目时,使用最多的基本就是 Cargo。

第一个 Rust 程序

我们可以通过命令 cargo new project-name 来创建一个 Rust 项目。

比如运行 cargo new hello-world:

image-20231206194316435

然后它就会为我们在当前目录中生成一个项目文件夹:

image-20231206194354353

这里简单对其介绍一下:

  • .git:如果本机安装了 Git,Cargo 默认可能会初始化这个版本库,也可以通过 --vcs none 禁用。
  • src:默认的源代码目录,二进制项目的入口通常是 src/main.rs。
  • .gitignore:告诉 Git 哪些文件不需要提交,通常会忽略 target 目录。
  • Cargo.toml:项目清单,里面记录项目名称、版本、edition 和依赖等信息。
  • target:编译产物目录,通常不提交到 Git。

这里的 Git 并不是 Rust 的一部分,而是一个通用的版本控制工具。比如知名的 GitHub 网站,就使用 Git 进行版本管理。不会使用 Git 的可以参考:Git 详解。

用记事本打开 Cargo.toml,就能看到下面这样的内容:

image-20231206194452154

对于想要使用的库,可以直接写在 [dependencies] 项下面,后面我会再详细介绍。

至于 TOML 配置文件的格式,可以参考文章:TOML 格式详解。

然后来到存放 Rust 代码的 src 目录:

image-20231206194546688

这里面默认有一个 main.rs 文件,其中后缀 .rs 是 Rust 源文件的后缀。对于二进制项目,它通常是程序的入口文件。

刚开始学习时先不要随意移动它。实际上,Cargo 也支持通过配置文件指定其他入口;库项目则通常使用 src/lib.rs。

同样,我们可以用记事本打开它:

image-20231206194609879

这里写的是一个函数:

  • fn:Rust 中的关键字,代表后面定义的是一个函数。
  • main:函数名称。对于二进制程序,main 是默认的入口函数。
  • ():函数的参数列表,最简单的函数可以写成 fn name() {}。
  • {}:函数体,也就是这个函数要执行的代码。这里使用 println!("Hello, world!"); 向终端打印一行文字。

println! 是 Rust 中的宏,用于向终端输出一行文字。

如果你学过 C/C++、Python、Java 等语言,前期可以直接把它当作一个 print 函数,只是要注意名称后面先有一个 !,然后才是 ()。

这里同时要注意,很多语句的结尾使用英文分号 ;。但 Rust 的代码块最后可以放一个表达式并省略分号,所以不能简单理解为“每一行都必须有分号”。

你也可以直接在下方编辑并运行这段代码,感受一下效果:

rust
待运行⌘↵
编辑仅保存在本页,刷新后恢复

现在回到控制台,进入这个文件夹,然后运行这段代码试一试:

cargo run

image-20231206194744354

然后就可以看到它成功运行并打印出 Hello, world!。

如果你学过 C/C++,会发现到目前为止,Rust 比 C/C++ 稍微复杂一点。毕竟 C/C++ 只需要一个源代码文件就能输出 Hello World,而 Rust 一开始就给我们生成了一个项目结构。

不过,项目结构正是 Cargo 方便的地方:代码、依赖和编译产物都有固定的位置,后面项目变大时会更容易管理。编译产物通常位于 target/debug 目录,Windows 下文件名一般以 .exe 结尾,Linux 和 macOS 下则不一定有扩展名:

image-20231206194829190

如果直接双击这个程序,窗口可能会一闪而过。这不是程序没有运行,而是因为它打印完字符串后就立即结束了;在终端中运行则可以直接看到输出。

除了 cargo run,Cargo 还提供了几个常用命令。如果只想检查代码,可以使用:

cargo check

如果只想生成编译产物,则使用:

cargo build

它默认构建 Debug 版本,适合开发和调试。

发布程序时可以构建 Release 版本:

cargo build --release

它会使用更强的优化配置,运行速度和最终体积通常更适合发布,但具体结果还会受到链接方式和项目配置影响。

image-20231206195029894

编辑器与开发工具

从上面我们可以看到,即使只用记事本也能开发,但那实在是太麻烦了。我们需要一个有代码提示、跳转和错误诊断的编辑器来提高效率。

个人推荐 VS Code,当然也可以根据自己的习惯选择其他编辑器。

可以从官网下载安装:VS Code

image-20231206195214739

根据自己的系统选择合适的版本下载安装。

如果终端提示找不到 code 命令,需要重新打开终端,或者按照 VS Code 官方文档将命令加入 PATH。

在控制台中进入项目文件夹,然后输入:code .

image-20231206195258082

这个 code 命令是 VS Code 提供的命令,用于让 VS Code 打开一个文件夹。

后面紧跟的 . 代表当前目录,也就是用 VS Code 打开当前项目目录。目录相关介绍可以参考文章:路径详解

然后你就能看到这个 Rust 项目在 VS Code 中被打开了:

image-20231206195407399

但 VS Code 只是一个编辑器,所以还需要安装 Rust 插件来提供代码分析功能。

点击左边的插件选项,搜索并安装 rust-analyzer :

image-20231206195605879

安装完成后,基本开发环境就配置好了。现在输入前几个字符时,就会自动弹出代码提示:

image-20231206195637196

这时,你只需要按 Enter 键就可以自动帮你填充代码。

插件还会在 main 函数上方显示运行按钮。不过初学时建议同时熟悉 cargo run,这样换到其他编辑器也不会忘记基本操作。

image-20231206195752641

如果需要断点调试,还需要编辑器和调试器配合,具体配置会因操作系统不同而有所区别:

image-20240218214704070

不会调试的可以参考文章:调试。

初识 Cargo 包管理

熟悉项目的创建和运行之后,再来试一下 Rust 官方示例中的 ferris-says,看看 Cargo 添加第三方库有多方便。

比如,我们想要在终端打印出下面这个图案:

image-20231206200441060

这里用到了 ferris-says 这个库。可以直接在终端运行:

cargo add ferris-says

也可以打开前面提到的 Cargo.toml,在 [dependencies] 项下面手动添加:

image-20231206200216706

后面的数字是这个库的版本要求。添加完成后运行 cargo check 或 cargo run,Cargo 就会解析并下载依赖。

运行命令后,项目文件夹中还会多出一个 Cargo.lock 文件。

这个文件用于记录当前项目解析得到的精确依赖版本,由 Cargo 自动维护。应用项目一般应该把它提交到版本库。

虽然看上去它和 Cargo.toml 有些重复,但两者的作用并不一样。Cargo.toml 由开发者指定项目元信息和依赖版本范围。

而 Cargo.lock 文件则用来锁定依赖的具体版本。比如当你依赖了 A、B 两个库,而 A、B 内部又都依赖了 C 库,那么此时应该选择哪个 C 的版本呢?

这便是 Cargo.lock 所做的事了。Cargo 会根据规则选择 C 库的具体版本并记录下来,这样团队成员和 CI 就能尽量使用同一组依赖。

现在回到代码中使用这个库。下面这个可运行示例已经包含了 Cargo.toml 依赖配置和 src/main.rs——顶部可以切换文件,修改后点击运行即可:

rust
待运行⌘↵
src/main.rs

第一次看到这段代码,你可能会感觉怎么有点复杂啊?

因为这一小段代码涉及到了 Rust 中相当多的概念,所以这里暂时不展开讲解。你可以先随意更改上面示例里的字符串:"Hello https://www.kucoding.com"

然后运行,就能在输出区看到图案了。

Cargo 下载的 crate 通常会缓存在当前用户的 ~/.cargo/registry 目录中,Git 依赖则会放在 ~/.cargo/git。当前项目的编译产物位于项目自己的 target 目录。

image-20231206200659690

这些目录由 Cargo 管理,不建议手动修改里面的内容。

总结

这是该系列教程的第一章,主要介绍了 Rust 的特点、安装、项目结构、编辑器配置和代码运行。

主要有以下几个命令需要稍微记忆一下:

  • cargo new:新建一个 Rust 项目
  • cargo check:快速检查代码
  • cargo run:编译并运行代码
  • cargo build:构建 Debug 版本
  • cargo build --release:构建 Release 版本
  • cargo fmt:格式化代码
  • cargo clippy:检查常见问题并给出建议
  • cargo test:运行测试

如果需要更新 Rust 工具链,运行下面的命令即可:

rustup update