让我们这就展开Rust的学习之旅吧。我们会有很多东西要学,但是每个旅行总有一个起点。在本章中,我们将讨论如下几点:
Hello, world!
程序cargo
这个Rust的包管理和项目创建工具学习的第一步是学会如何安装Rust。我们将会通过rustup
来下载Rust,rustup
是一个命令行工具,主要用途是用来管理Rust的版本和与Rust相关的工具。所以,请确保你有稳定的网络连接用于下载。
出于某些原因,你不想使用
rustup
来安装Rust,你也可以在the Rust installation page 找到其它安装方式。
下面的步骤将会安装最新版本的Rust编译器。Rust保证在本书中涉及到的程序示例在未来新版本的Rust下也能成功编译,但是不同版本间输出可能略有不同,但请勿担心,这些不同只是因为Rust改善了错误和警告的消息。换句话说,无论你安装了任何更新的稳定版Rust,本书中的例子仍会按照你所期望的样子执行。
命令行标记符
在本书中,我们会提供一些终端中的指令。我们会通过一个$
作为标记符来告诉你这是条终端指令,你并不须要在输入指令时输入这个$
。 如果你输入了$
,会适得其反,指令反倒无法执行。另外多说一句,PowerShell的例子将使用>
而不是$
。
rustup
如果你是使用Linux或者macOS的大佬,请打开一个终端窗口,并输入如下指令:
$ curl https://sh.rustup.rs -sSf | sh
这个指令将下载一个脚本并且执行 rustup
的安装,同时也会安装最新稳定版本的Rust。安装过程中也许会提示你输入密码。安装成功,你将看到如下的一条信息:
Rust is installed now. Great!
这个安装脚本将会在你下次登录系统时,自动将Rust添加到PATH环境变量中。安装结束后,如果你不想重新登录就立即使用,你也可以通过执行以下命令来手动将Rust添加进PATH中:
$ source $HOME/.cargo/env
或者,你也可以在你的 ~/.bash_profile里添加如下命令:
$ export PATH="$HOME/.cargo/bin:$PATH"
在一些特殊情况下,你可能额外还须要安装某些类型的链接器(linker)。譬如当你安装完毕并试图编译一个Rust程序时,系统提示了报错消息并指明链接器无法执行。这意味着你的系统中未安装对应的链接器,你必须要手动安装它们。C编译器通常会有正确的链接器。所以请查阅系统文档,找到如何安装C编译器相关的资料。很多常用的Rust包都是由C写成,所以须要一个C编译器。因此,安装C编译器是非常值得的。
rustup
Windows用户,请访问https://www.rust-lang.org/tools/install ,并按照里面的说明来安装Rust。在安装过程中,有时你会收到提示信息,要求你安装C++ build tools for Visual Studio 2013或者其它更新的版本。遇到这种情况,最简单的方法就是安装Rust前直接先安装Build Tools for Visual Studio 2019。它在这个网页的 Other Tools and Frameworks目录下。
本书接下来的内容中,所有的指令既能在 cmd.exe 也能在 PowerShell 下正常运行。假如有一些特别的不同点,我们也将解释该如何用。
当你通过rustup
安装完Rust后,更新Rust到最新版也是很容易的。在你的Shell中执行如下指令即可:
$ rustup update
卸载 Rust 和 rustup
则使用如下指令:
$ rustup self uninstall
检查你的Rust是否真的安装成功,请使用如下指令:
$ rustc --version
执行完后,你应该可以看到当前安装的Rust版本,对应的Hash值,版本发布日期。格式应该像下面一样:
rustc x.y.z (abcabcabc yyyy-mm-dd)
如果你没有看到上面的消息,而你又是用的Windows,请检查下Rust是否已经加到你系统的 %PATH%
环境变量中。如果你确定这些都准确无误,然而Rust还是无法使用。这里也有一堆地方可以让你寻求帮助。最简单的是官方网站the official Rust Discord上的新手频道,这里你可以与其它的锈菌(Rustaceans,Rust用户的绰号)交流,他们不会吝惜为你提供帮助。其它靠谱的途径还有官方的the Users forum和大名鼎鼎的 Stack Overflow 。
安装程序还包含一份该文档的备份,以便于你在线下阅读。使用rustup doc
会在你的浏览器中打开本地帮助文档 (帮助文档不支持命令行模式 )。
任何时候当你不确定一个标准库的功能该如何使用时,可以通过API文档来找下这个功能的相关说明。
读到这里,想必你已完成了Rust的安装,那么恭喜你,按照老祖宗留下的惯例,我们就该开始用Rust来写一个 Hello, world!
的程序了。
本书假定你已掌握命令行的基础操作。Rust对于你的编辑器或是IDE没有任何特殊要求,你可以选择不在命令行下编写Rust程序,使用你自己喜欢的IDE就好了,just feel free。事实上,现在很多IDE对Rust已经有不同程度的支持了,你不妨查看下你IDE的相关文档,说不定就能有所收获。Rust的团队近期已在关注如何能让Rust更好的受到IDE支持,并且已经获得了相当积极的反馈。
你需要创建一个目录来专门存放你的Rust代码,虽然Rust代码存放的位置并不会有什么影响,但鉴于本书中会有很多练习和项目,我们建议你在自己的Home目录下创建一个 projects 文件夹来存放所有练习用到的项目。
那么打开一个终端窗口,输入以下指令来创建一个 projects 目录并将 Hello, world! 项目放进去。
Linux, macOS, PowerShell:
$ mkdir ~/projects
$ cd ~/projects
$ mkdir hello_world
$ cd hello_world
Windows CMD:
> mkdir "%USERPROFILE%\projects"
> cd /d "%USERPROFILE%\projects"
> mkdir hello_world
> cd hello_world
接下来请在 hello_word 目录下新建一个源码文件 main.rs 。Rust的文件扩展名是 .rs 。如果你的源码文件名中包含两个单词,请使用下划线来分隔它们。譬如使用 hello_world.rs 而不是 helloworld.rs。
现在请打开 main.rs 并输入如下的代码:
fn main() {
println!("Hello, world!");
}
译者注:CSDN Markdown暂不支持rust语法高亮,所以我把代码块标注为了 js,如觉得不方便阅读,可去官网查看原文档。
编辑完成,保存文件,并打开终端窗口。
Linux & maxOS 输入如下指令编译程序并执行:
$ rustc main.rs
$ ./main
Hello, world!
Windows 下略有不同,使用 .\main.exe
而不是 ./main
:
> rustc main.rs
> .\main.exe
Hello, world!
无论你是什么操作系统,你的终端上都应该会输出文本 Hello, world!
。如果你没有看到这个输出,请查看之前 TroubleShooting 中的内容来寻求帮助。
如果 Hello, world!
正常显示,那么恭喜你,你正式写了一个Rust程序,你已经是一个Rust程序员了,欢迎。
让我们回过头来看下我们的 Hello, world!
程序。以下是我们程序的第一部分:
fn main() {
}
这些代码定义了一个Rust的函数。要注意,main
函数是非常特别的,它是每一个Rust程序执行时首先会调用的函数。我们在程序的第一行定义了一个叫做 main
的程序,它不带任何参数也没有返回值。如果一个函数有参数,它们应当放在函数名后紧跟的括号 ()
中间。
而这个函数的主体部分,则是由一对花括号 {}
包裹。有一个很好的习惯是将 {
紧跟在函数定义的行末并与在它与)
中加个空格,而将 }
单独放到函数的最后一行。
捎带一提,在编写这个教程的时候,一个Rust代码的自动格式化工具 rustfmt
已在紧锣密鼓的开发中。如果你想自己的Rust项目和其他人一样有一个统一的标准代码格式,你可以使用 rustfmt
来格式你的代码。Rust的团队计划将这个工具包进标准的Rust分发版本中,就像 rustc
。当你读到这篇文章时,可能这个工具已经安装到你的电脑中了。你可以在网上的文档中获取有关这个工具的详细信息。
译者注:当前Rust标准安装包中已包含
rustfmt
工具了,只要使用rustfmt main.rs
就能格式化你的代码。
在我们的 main
函数中,是如下代码:
println!("Hello, world!");
这行代码实现了我们这个程序将文本输出到显示器上的功能。这里有 4
个细节需要我们留意。
println!
被称作Rust宏。如果在这你要使用函数,那就得改为 println
。我们会在第19章中对宏作详细讨论,但当前,你只要知道 !
代表我们使用的是宏而非普通的函数。"Hello, world!"
这串字符。我们把它当做参数传给 println!
, 将它打印在屏幕上。;
,这个符号标注这个表达式已经结束。绝大多数 的Rust代码都以 ;
标记结束。你刚刚已经运行了一个热乎的程序,那我们来好好看下每步发生了什么吧。
在运行Rust程序前,你需要通过Rust编译器将源码进行编译,即使用 rustc
命令并将源码文件名提供给它:
$ rustc main.rs
如果你有C或是C++的背景,你就会意识到,这和 gcc
clang
非常类似。编译完成后,Rust会产生一个可执行的二进制文件。
Linux & macOS & PowerShell 环境下,使用 ls
命令,我们可以看到两个文件:
$ ls
main main.rs
Windows下使用CMD工具,你则会看到三个文件:
> dir /B %= the /B option says to only show the file names =%
main.exe
main.pdb
main.rs
其中源码文件都是扩展名为 .rs
,Linux&macOS编译后产生 main 这个可执行文件,而Windows在产生 main.exe
外,还会多一个包含debug信息的 .pdb
文件。你可以直接运行 main
或者 main.exe
:
$ ./main # or .\main.exe on Windows
如果你很熟悉一些动态语言,譬如 Ruby,Python或是Javascript,你或许并不需要分别编译和运行程序。Rust是一个 预编译 语言,换句话说就是你可以在编译好后将产生的可执行文件发给任何人,别人可以在自己的电脑上运行这些程序——无论他们是否在本地安装有Rust。如果你给的是 .rb .py .js,别人就不得不分别在本地安装好Ruby,Pyhon 和 Javascript 运行环境。但这些动态语言,你只需要一条指令就能编译并运行它们。 所有东西都是编程语言在设计时权衡得到的结果。
使用 rustc
编译一些简单的程序很轻松,但随着你项目的增长,你就想要能管理到它的方方面面,并期望能够更简单的共享你的代码。下一步,我们就会为你介绍 Cargo 这个工具,它会帮助你写出真正有用的Rust程序。
Cargo 是 Rust 的构建系统和包管理工具。许多Rustaceans都使用这个工具来管理他们的Rust项目,因为Cargo可以帮助你处理很多工作,譬如构建你的代码,下载你程序须要的库,甚至构建一个库。(我们称其为库,但在代码中,称呼其为 dependencies 即依赖项)
像我们之前创建的那个非常简单的程序,它并没有任何依赖项。如果我们使用Cargo来搭建 Hello, world!
程序,我们只会用到它的很小一部分功能。如果你着手写一个更复杂的程序,你可能就要添加依赖项了,这时使用Cargo,你会发现添加依赖项变得非常简单。
因为很大一部分的Rust项目都在使用Cargo,本书接下来也就假定你也是使用的Cargo。如果你是按照官方的安装工具完成Rust的安装,那Cargo已经也被安装进了你的系统。万一你手贱,通过其它的方式安装,那请使用下面的命令检查下Cargo是否有安装:
$ cargo --version
如果你看到一个版本号,那说明Cargo已经安装。如果你看到像是 command not found
或者其它之类的报错, 请找下你安装Rust时参考的文档,里面是否有说明如何单独安装Cargo。
那么现在,就让我们来使用Cargo创建一个新的项目,来看下和我们原始的 Hello, world!
项目有什么不同。首先请在命令行下讲工作区切换到我们的 projects 目录下,并执行如下指令:
$ cargo new hello_cargo
$ cd hello_cargo
第一条指令会在当前目录下创建一个新的文件夹 hello_cargo,我们将我们的项目命名为 hello_cargo,同时Cargo会将项目的相关文件创建到一个以项目命名的文件夹下。
进入 hello_cargo目录,并查看文件。你会发现Cargo为我们创建了两个文件:Cargo.toml 和 src 文件夹,同时 src 文件夹下还有一个 main.rs 文件。并且在项目文件夹下,已经初始化了一个Git代码库并生成了一个 .gitignore 文件。
Git是一个流行的版本控制系统。你也可以在
cargo new
时选择使用其它的版本控制系统,或是使用--vcs
这个参数来取消版本控制。试下cargo new --help
来查看可以使用的参数。
让我们来看下 Cargo.toml 的内容:
[package]
name = "hello_cargo"
version = "0.1.0"
authors = ["Your Name "]
edition = "2018"
[dependencies]
这是一个 TOML 格式的文件,这是Cargo的配置文件格式。
第一行 [package]
标记了有关这个包的配置的段落的开头。当我们有更多的信息想要添加进配置文件时,我们可能会须要添加相应的段落。
接下来四行配置信息,在Cargo编译你的程序时会用到:包名,版本,作者和Rust的版本。Cargo初始化项目时,会从环境变量中获取你的名字和邮件,如果这些信息不准确,可打开这个文件修改并保存。关于版本 edition
,我们会在附录E中展开讨论。
最后一行 [dependencies]
标记了依赖项清单的段落开头。在Rust中,源码包被称呼为 crates
箱。在这个项目中,我们不会引用任何crates。但在第二章中,我们会用到依赖项。
现在我们打开 src/main.rs :
fn main() {
println!("Hello, world!");
}
Cargo已经为我们创建了一个 Hello, world!
程序,而且和我们之前创建的程序一毛一样。目前为止,用Cargo创建的项目和我们之前项目的区别仅在于Cargo将源码放在了 src 目录下,此外Cargo项目的根目录下会多一个 Cargo.toml 配置文件。
Cargo期望我们将所有源文件都放在 src 目录下。项目的根目录只是用来放诸如 README ,或是 License信息,配置文件和其它与你代码没有任何直接关系的东西。使用Cargo可以帮助你组织你的项目,所有的东西都在一起且都放在它们该在的地方。
如果你在创建项目之初没有使用Cargo,就像我们之前的 Hello, world!
。你可以新建一个目录,将源码放进目录下的 src 文件夹中,同时在 src 的上层目录下创建一个 Cargo.toml 来将其变成Cargo项目,从而使得这个项目能被Cargo管理。
现在我们来一起看下运行Cargo项目和我们之前的项目有何不同。首先我们将命令行工作区切换到 hello_cargo 目录,同时执行下面的命令:
$ cargo build
Compiling hello_cargo v0.1.0 (file:///projects/hello_cargo)
Finished dev [unoptimized + debuginfo] target(s) in 2.85 secs
这条指令会创建一个 hello_cargo/target/debug/hello_cargo 可执行文件(hello\target\debug\hello_cargo.exe on Windows),注意,可执行文件的路径不是在你当前的工作区下。你可以通过如下指令运行它们:
$ ./target/debug/hello_cargo # or .\target\debug\hello_cargo.exe on Windows
Hello, world!
如果一切运行正常,Hello, world!
应该会在终端显示出来。运行 cargo build
同时会在项目的根目录下创建一个 Cargo.lock 文件,这个文件会保留记录项目依赖项的精确版本。我们的项目没有用到任何依赖项,所以lock文件对于它并没什么用。但是你千万别去尝试手工修改这个lock文件,Cargo会帮你管理它的内容。
我们刚刚通过 cargo build
编译了源码并同时创建了可执行文件,然后通过 ./target/debug/hello_carg
运行了我们的程序。但事实上,我们可以直接在项目根目录下通过 cargo run
这个命令直接编译源码并执行:
$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
Running `target/debug/hello_cargo`
Hello, world!
你可能注意到了,这次输出,我们并没有看到Cargo去编译hello_cargo
,这是因为Cargo觉察到项目文件没有被修改,所以它直接去调用二进制文件了。如果你修改过了你的源码,Cargo会在运行程序前,重新编译项目并创建可执行文件,然后你会看到类似下面的输出:
$ cargo run
Compiling hello_cargo v0.1.0 (file:///projects/hello_cargo)
Finished dev [unoptimized + debuginfo] target(s) in 0.33 secs
Running `target/debug/hello_cargo`
Hello, world!
Cargo还提供了一个指令 cargo check
。这个指令会快速检查你的代码是否能够通过编译,但它不回去创建可执行文件。
$ cargo check
Checking hello_cargo v0.1.0 (file:///projects/hello_cargo)
Finished dev [unoptimized + debuginfo] target(s) in 0.32 secs
那为什么我们不需要一个可执行文件呢?通常情况下,cargo check
执行的速度是远快于cargo build
的。它跳过了创建可执行文件这步。当你频繁检查正在编写的代码时,使用 cargo check
显然更加方便快捷。因此,很多Rustaceans会周期性的使用cargo check
来确保他们的代码可以被编译。当确定他们须要用到可执行文件时,他们才会去使用 cargo build
。
来让我们回顾下我们目前学到的有关Cargo的知识:
cargo build
和 cargo check
来创建一个项目cargo run
这一条指令来运行Cargo项目使用Cargo的额外优势,就是可以在不同操作系统中使用相同的命令。基于这点,在接下来的教程中,我们将不再分别提供 Linux & macOS & Windows 下不同的指令。
当你最终决定发布你的项目时,你可以使用 cargo build --release
来编译它,Cargo会提供额外的优化。可执行文件会被创建在 target/release 而非 target/debug 下。Cargo提供的优化能提升你Rust指令的运行速度,但不可避免的是会加长花在编译上的时间。使用 release
是为了照顾到两种场景。在开发时,不用release
,能够提升重构项目的速度;而交付给用户时,用户不会去重构项目,使用release
确保产生的可执行文件能够尽可能快速的运行。所以要对你的代码运行时间做基准测试,记得使用cargo build --release
,并对 target/release 下的可执行文件去做基准测试,因为这才是最优的结果。
对于简单的项目,Cargo并没有提供太多价值,只是调用了rustc
。但是随着你的项目不断成长,Cargo会证明它自己的价值。对于一个包含多个箱的复杂项目,使用Cargol来协助创建会容易许多。
尽管hello_cargo
项目很简单,但它已经用到了很多在你接下来Rust生涯中涉及的工具。实际上,如果你想使用一个已有的Rust项目,你可以直接使用以下的Git指令来检出源码,并构建:
$ git clone someurl.com/someproject
$ cd someproject
$ cargo build
对于更多有关Cargo的介绍,请访问官方文档cargo。
你已经踏上了Rust的旅程,在这一章中,你掌握了如下的知识:
rustup
安装最新的稳定版Rustrustc
运行一个 Hello, world!
程序趁热打铁,现在是时候写一个更加贴近现实的程序来让我们熟悉阅读和编写Rust代码。在接下来的第二章中,我们将创建一个猜数字的游戏程序。如果你想先了解Rust程序的一些基础概念,你可以先去阅读第三章,然后回过头来再看第二章。
官方原文地址:Getting Started