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()
函数,提供