案例出处是《Rust权威指南》,书中有更加详细的解释。从这个例子中,我们可以了解到 rust 的两个操作:
- 如何从控制台读取用户输入
- rust 如何生成随机数
代码格式化
编译器可在保存时对代码做格式化处理,底层调用 rustfmt
来实现,代码内容基本和书中内容一致。代码中使用 use
语句显示的导入了标准库 std 中的 io
和 cmp
包,因为 rand
包并不在标准库中,所以,我们在 dependencies 声明中引入 rand 包。
use rand::Rng;
use std::{cmp::Ordering, io};
fn main() {
let secret_number = rand::thread_rng().gen_range(1, 101);
loop {
let mut guess = String::new();
io::stdin()
.read_line(&mut guess)
.expect("failed to read line");
let guess: u32 = match guess.trim().parse() {
Ok(num) => num,
Err(err) => {
println!("parse error: {err}");
continue;
}
};
match guess.cmp(&secret_number) {
Ordering::Equal => {
println!("success");
break;
}
Ordering::Greater => println!("too big"),
Ordering::Less => println!("too small"),
}
}
}
从控制台读取输入
io::stdin()
中的::
语法声明stdin是io类型的一个关联函数,rust 会针对类型本身来定义函数,而不是针对某个特定实例,同样还有 String::new()
方法调用。
read_line
将控制台输入的内容存储到传入的参数中,同时返回 io::Result
类型值。这个类型属于枚举类型,rust 主要用来做错误处理。
生成随机数
针对 dependencies 中 rand 包的声明,rust 按照标准的语义化版本来处理版本号。版本声明中的 0.3.14实际上是^0.3.14的一个简写,它表示“任何与0.3.14版本公共API相兼容的版本”
[dependencies]
rand = "0.3.14"
程序最终使用的 rand 版本会记录在 Cargo.lock
文件中,通过 Cargo.lock
中详细的版本依赖信息,才保证了我们任何时候编译的结果都是相同的。除第一次构建程序外,再次构建程序时,Cargo 会优先检查 Cargo.lock
,假如文件中存在已经指明具体版本的依赖库,那么它就会跳过计算版本号的过程,并直接使用文件中指明的版本。这使得我们拥有了一个自动化的、可重现的构建系统。
下面记录了 Cargo.lock
中记录了项目依赖的 rand 包详细信息:
当你确实想要升级某个依赖包时,Cargo提供了一个专用命令:update,它会强制Cargo忽略Cargo.lock
文件,并重新计算出所有依赖包中符合Cargo.toml 声明的最新版本。假如命令运行成功,Cargo就会将更新后的版本号写入Cargo.lock文件,并覆盖之前的内容。