Rust基础笔记(1):基础结构
序
此笔记为在学习Rust圣经《The Rust Programming Language》时记录的笔记,为基础学习
中文版书籍:Rust 程序设计语言 - Rust 程序设计语言 简体中文版 (kaisery.github.io)
安装过程不再赘述,可直接参考Rust官方网站的安装过程
官方网站地址:Rust Programming Language (rust-lang.org)
本人开发环境为:
- ManjaroWSL2
 - Clion
 
学习Rust纯属为个人一时兴起,本笔记随时弃坑。
一个简单的Rust程序
1  | use std::io;  | 
运行结果:

这个程序的逻辑很简单,就是处理用户的输入,把用户的输入进行输出。
但是这个程序拥有了Rust程序的基本结构,我们从上直下解析这个程序:
1  | use std::io;  | 
为了获取的用户输入,我们需要导入输入输出库(input / output),即io库。io库来自于标准库,即std。这个操作类似于c语言的include,或者是Java的import。
在默认的情况下,Rust会自动导入部分标准库到每个程序作用域,这部分被称为预导入,若我们所需要用的不在其中,则需要我们手动使用use显式导入。
1  | fn main() {  | 
fn用于声明新函数,main函数是程序的入口点。
1  | println!("Guess the number!");  | 
在这里println!用于在屏幕中打印字符串。
**注意:**它并不是一个函数,而是一个宏,!的基本上都是宏。
使用变量存储值
1  | let mut guess = String::new();  | 
在这里我们创建了一个空的字符串变量用于存储输入,我们注意到,与很多常见的编程语言不同,我们申明用了两个关键词let mut:
这是因为Rust中,变量默认是不可变的,因此我们如果使用let guess的话,会使得guess类似其他编程语言中的常量一样,不可变,因此我们还要通过mut关键词使得变量可变。
=是在告诉Rust,我们想将某个值绑定在变量上。因此我们将String::new()的结果绑定到了guess上,它的结果是一个String的新实例。
::new()注意,这里的new()并不是String的特定函数,而是一个跟Java静态方法一样的关联函数。在这里::就表明了new是String的关联函数。new函数是创建类型实例的惯用函数。
接受输入与异常处理
1  | io::stdin()  | 
现在我们调用一开始导入的io库中的函数接受用户的输入,我们使用了stdin函数,stdin函数返回了一个std::io::Stdin的实例,这是终端标准输入句柄类型。
.read_line(&mut guess)调用了read_line方法,从句柄中获取到用户的一行输入,并将其追加到参数中,因为我们传入的参数应该是可变的。
&代表了引用,它使得程序中不同处的代码可以访问同一处的数据。它与变量相同,默认都是不可变,因此我们需要将其写成&mut guess以使其可变。
.expect("Failed to read line.")的作用就是异常处理。read_line会返回一个Result类型,Result是一个枚举类型,其中包含了Ok与Err,分别代表操作成功与失败。
Result类型的实例拥有一个expect方法,若Result实例的值为Err,expect方法会导致程序崩溃,并显示expect中传入的值,若Result实例的值为Ok,则会原样返回Ok中的值。
占位符打印值
1  | println!("Your guessed: {guess}");  | 
这行代码打印了保存在guess变量中用户输入的值。里面的{}为一个预留给变量类的占位符号,我们除了把变量直接写在{}中,我们还可以在双引号的外面按顺序写值,这个跟c类似,应该不陌生:
1  | println!("x = {}, y = {}", x, y);  | 
第一个占位符使用第一个值,第二个占用符使用第二个值…以此类推。
引入Crate实现更多功能
Crate是一个Rust代码包,是Rust在编译时最小的代码单位,它有两种形式,二进制Crate和库Crate:
二进制Crate是一个可执行的程序,比如我们写的一个简单的Rust程序。它们必须要一个main函数来确定程序的入口;
库Crate与其他编程语言中的library概念一致,包含了可以被其他程序使用的代码,它们提供了一些诸如函数之类的东西,使得其他项目能够使用。它们并不能自执行。
上面我们介绍了Crate,下面我们要用到一个外部的库Crate来完善我们的程序。
一个简单的Rust程序编写了一个让用户输入,然后程序输出用户的输入的程序,从println!的内容我们可以看出我们并不是想做出一个这么简单的程序,我们是想让用户来猜我们的神秘数字。
为了生成一个随机的神秘数字,我们需要用到随机数,Rust标准库中尚未包含随机数的功能,但是我们可以引入包含随机数功能的rand库Crate。
我们需要去修改Cargo.toml文件,引入一个rand引用,现在我们将下面一行添加到[dependencies]下:
1  | rand = "0.8.3"  | 
现在我们不修改任何代码,构建项目,我们会发现Cargo帮我们下载了rand和它依赖的一系列库Crate,Cargo会帮我们检测需要新增的Crate和我们是否修改了代码,并帮我完成下载与构建。
在Cargo.toml中的依赖版本信息,并不是指定某一个版本,而是一个区间——一个大于等于0.8.3且小于0.9.0的版本。
为了我们的构建结果是可以被任何人复刻的,Cargo.lock文件会帮助每个人的Cargo只会使用指定的依赖版本,除非手动去指定其他版本。我们会将Cargo.lock纳入版本控制中,以保证每个人都可以复刻这个构建结果。
在确实需要更新Crate的版本时,我们还可以通过Cargo update忽视Cargo.lock文件,并重新计算符合Cargo.toml声明的最新版本,将其更新且写入到Cargo.lock文件中。
让我们开始使用rand来生成一个随机数字,修改我们的代码:
1  | use std::io;  | 
我们依旧是从上往下看我们新增的代码:
1  | use rand::Rng;  | 
这里导入了属于rand包里的一个trait——Rng。trait概念类似于其他语言中的接口,里面会定义很多方法。
1  | let secret_number = rand::thread_rng().gen_range(1..=100);  | 
这里调用了rand::thread_rng()函数,提供