Rust中文翻译5

时间:2022-09-18 14:53:54
Page 25
欢迎!这一节通过构建一个Rust工程来介绍一些Rust语言的基本指导原则.你会从高层次来概览整个Rust,忽略掉细节. 如果你喜欢先学习基本语法,可以直接去第五章.
3.1 猜数字游戏 我们的第一个工程,我们实现一个经典的初学者编程问题:猜数字问题.下面是他的工作原理:我们的程序会产生一个1到100的随机数.程序会提示我们输入一个数字,根据输入内容会提示我们偏大还是偏小.只要我们才对了,他就会恭喜我们.听起来不错吧?
3.1.1 设置 让我们设置一个新工程.转到你的工程目录.还记得我们为hello_world工程创建了一个目录结构和Cargo.toml文件么?Cargo使用一个命令来为我们做到这些. 让我们回顾一下: $ cd ~/projects $ cargo new guessing_name --bin $ cd guessing_name
我们传递了工程的名字,通过cargo new命令,并且使用了--bin标识,这样我们就创建了一个二进制可执行程序,而不是一个库. 看一下生成的Cargo.toml文件:
Page 26
[package]
name = "guessing_game" version = "0.0.1" authors = ["Your Name <you@example.com>"]
Cargo从你的环境信息得到了上述信息.如果有误,你可以修改它. 最后Cargo创建了'Hello,world!'文件,看一下src/main.rs: fn main() {     println!("Hello, world!"); }
我们用Cargo编译一下: Rust中文翻译5

漂亮!再次打开你的src/main.rs文件.我们会把所有代码写入这个文件.
在我们继续以前,让我来给你介绍另一个Cargo命令:run.cargo run和build命令类似,但是他会同时运行生成的可执行程序.试试吧: Rust中文翻译5
Rust中文翻译5 非常好!当你需要快速迭代一个工程的时候run命令用起来非常称手.我们的工程就是这样一个工程.我们需要快速测试每一次迭代,以便于我们进行下一步.
3.1.2 处理一次猜数 让我们开始吧!我们的猜数程序需要完成的第一件事就是如需我们输入一个数.在src/main.rs中输入如下代码:
use std::io;
fn main() {      println!("Gurss the number!");      println!("Please input your guess.");      let mut guess = String::new();      io::stdin().read)line(&mut guess)           .ok()           .expect("Failed to read line");      println!("You guessed: {}", guess); } 这里太多东西了!让我们逐个字节的分析.
use std::io; 我们需要处理用户输入,然后把他打印出来.因此,我们需要从标准库中引入io库.Rust只引入很少的一些东西到我们的代码中,称为"prelude".如果不在prelude库中的,我们需要直接使用它. fn main() { 正如你已经看到的一样,main函数是你的程序的入口点.fn语法声明了一个函数,()说明这里没有参数.{是函数开始的地方.因为我们没有包含返回值,默认值是(),一个空的元组(tuple).      println!("Guess the number!");      println!("Please input your guess."); 我们之前学过了println!是一个宏,它将一个字符串打印到屏幕.      let mut guess = String::new(); 现在我们来看有趣的事情!这一行里有很多东西.第一个要说的是这是一个let声明式(let statement),他用来创造一个可变绑定(variable bindings).他们采用这种形式: let foo = bar; 这一行创建了一个新的绑定,名字叫foo,它绑定了一个值bar.在很多余雁中,这被称作一个变量(variable),但是Rust的可变绑定还有一些小技巧. 例如,默认他们都是不可变的.这也就是为什么我们的例子中要使用一个mut关键字,它是一个绑定编程了可变绑定,而不是不可变.let关键字也不是给等号左边分配一个名字,它其实是接受了一个模式(pattern).我们会在稍后使用更多的模式.它使用起来很简单: let foo = 5; // immutable. let mut bar = 5; // mutable 哦,//会开始一个注释,直到行末.Rust忽略所有的注释. 所以现在我们知道了let mut guess会引入一个名为guess的可变绑定,但是我们要看看=号右边的东西,它是一个String::new()类型. String是一个string类型,由标准库提供.一个String是一段可增长的,UTF-8编码的文本. ::new()语法使用了::,因为这是一个类型的关联方法.也就是说,它和String类型关联,而不是一个具体的String类型的对象.有些语言称它为"静态方法". 这个方法叫做new(),因为它创造了一个新的空的字符串.你可以在很多类型中都找到new()方法,它是一个类型创造一个新的值的通用名称. 让我们继续:      io::stdin().read_line(&mut guess)           .ok()           .expect("Failed to read line"); 这里有很多东西!让我们逐个字节来解释.首先是这个: io::stdin()
还记得我们在程序的第一行使用的这个std::io么?我们在调用一个关联方法.如果我们不使用std::io的话,我们可以将这个行写作:std::io::stdin(). 这个具体的方法会为你的终端的标准输入返回一个句柄.确切的说是一个std::io::Stdin. 接下来的部分,我们使用这个句柄来获得用户的输入: .read_line(&mut guess)
这里我们在句柄上调用了read_line()方法.方法和关联方法类似,只不过它对一个类型的具体对象起作用,而不是这个类型本身.我们还给这个方法传递了一个参数:&mut guess.
还记得上面的guess绑定么?我们说他是一个可变绑定.然而,read_line函数并不使用一个String类型的参数.它使用一个&mut String(一个String类型的mut引用).Rust有一个特性叫做引用(references),它可以让你拥有一个数据的多个引用,这样可以减少拷贝.
Page 29
引用是一个复杂的特性,它是Rust最有卖点的几个特性之一,Rust像我们展示了引用是多么的安全,使用起来多么的方便.但是现在,为了完成我们的程序我们还不需要了解太多关于它的细节.目前,我们只需要知道引用和绑定一样,默认是不可变的.因此,这里我们使用了&mut guess,而不是&guess.
为什么read_line需要一个可变引用呢?因为它的任务是处理用户的输入,然后把它们赋值给字符串.所以它需要一个string作为参数然后可以增加它的内容,所以它需要可变.
但我们这一个行代码其实没有做完所有工作.在文本上的一行,只是在逻辑上的一行的第一个部分:      .ok()      .expect("Failed to read line");
当你使用.foo()语法调用时,你可以另起一行并插入一些空白字符. 这可以帮你把很长的一行代码分成多行,我们当然可以写成这样: io::stdin().read_line(&mut guess).ok().expect("Faild to read line"); 但是很难阅读.所以我们把他分开,3行分别是3个函数调用.我们已经讲过了read_line(),那么ok()和expect()呢?我们刚才说了read_line()函数获取用户输入到&mut String中的值,但是它还会返回一个值:在这里是一个io::Result.Rust标准库中有很多类型的Result:一个基类的Result,还有很多版本的子类型,例如io::Result.
Result类型的目的是对错误信息进行处理.Result类型的变量和其他类型一样,有很多方法可供使用.在本例中,io::Result类型有一个ok()方法,它的意思是"我们假设这个值是正确的,如果不是的话抛出一个错误信息".为什么抛出?对于一个基本的程序,我们希望打印一个通用的错误,作为我们无法继续运行的基本含义.ok()方法返回了一个值,它有另一个方法:expect().这个expect()方法处理一个调用此方法时产生的值,如果此值不是成功的,那么就会调用panic!,并使用你传给他的信息.一个panic!会导致我们的程序崩溃,并且显示这个信息.
如果我们不调用这两个函数,我们的程序会通过编译,但是会有如下警告: Rust中文翻译5

Page 30
Rust警告我们没有使用Result值.这个警告来自io::Result的一个特殊的注解.Rust在告诉你你没有处理一个可能的错误.处理这个错误的正确方法就是为他编写一个错误处理.幸运的是,如果当错误发生的时候我们希望程序崩溃,我们就可以调用这两个小方法.如果我们希望从错误中恢复,我们需要做一些其他事情,但是我们留在以后的工程再讲解.
我们第一个程序还剩最后一行:      println!("You guessed: {}", guess); }
这回打印出我们输入并保存的值.{}是一个占位符,我们把guess当作参数传递给他.如果我们有多个{},我们需要传递多个参数. let x = 5; let y = 10; println!("x and y: {} and {}", x, y);
简单. 总之,这就是所有的东西.我们使用cargo run来运行它: Rust中文翻译5

好了!我们第一部分结束了:我们可以从键盘输入并且打印出来一个值.