对于一门编程语言其需要具备根据条件状态来执行不同的代码或者根据条件状态来决定是否继续重复执行代码。通常这样的结构就是 if 表达式和 loops。
if 表达式
if 表达式允许你基于条件状态来执行不同的代码。
1 2 3 4 5 6 7 8 9
fnmain() { letnumber = 3;
if number < 5 { println!("condition was true"); } else { println!("condition was false"); } }
if 表达式使用 if 关键字开头,接着一个条件状态。在这个例子中,条件状态检查 number 变量是否小于 5。然后我们把条件为 true 时执行的代码块用花括号括起来放在后面,这样的一块代码在 rust 中被称为 arms,就像 match 表达式中一样。
我们还能在后面继续写一个 else 表达式,这个不是必须的。这个 arm 是在条件为 false 时执行的。如果我们不提供 else 表达式,那么当条件为 false 时程序就会直接跳过整段 if 代码块去执行后面的代码。
执行这段程序:
1 2 3 4 5
$ cargo run Compiling branches v0.1.0 (file:///projects/branches) Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.31s Running `target/debug/branches` condition was true
如果把 number 改为 7,再执行程序,可以得到:
1 2 3 4 5
$ cargo run Compiling branches v0.1.0 (file:///projects/branches) Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.31s Running `target/debug/branches` condition was false
条件状态的类型必须是 bool,否则会报错。例如:
1 2 3 4 5 6 7
fnmain() { letnumber = 3;
if number { println!("number was three"); } }
这里条件状态的值为 3, Rust 会报错:
1 2 3 4 5 6 7 8 9 10
$ cargo run Compiling branches v0.1.0 (file:///projects/branches) error[E0308]: mismatched types --> src/main.rs:4:8 | 4 | if number { | ^^^^^^ expected `bool`, found integer
For more information about this error, try `rustc --explain E0308`. error: could not compile `branches` (bin "branches") due to 1 previous error
报错信息指出 if 表达式期望传入的值是 bool 而不是一个整型。Rust 不会像其他一些语言一样隐式地将非 bool 型的值转换为 bool 类型。
使用 else if 处理多个条件
我们还能加入 else if 表达式来处理更多的条件:
1 2 3 4 5 6 7 8 9 10 11 12 13
fnmain() { letnumber = 6;
if number % 4 == 0 { println!("number is divisible by 4"); } elseif number % 3 == 0 { println!("number is divisible by 3"); } elseif number % 2 == 0 { println!("number is divisible by 2"); } else { println!("number is not divisible by 4, 3, or 2"); } }
这个程序中有 4 条路可以走,如果运行它:
1 2 3 4 5
$ cargo run Compiling branches v0.1.0 (file:///projects/branches) Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.31s Running `target/debug/branches` number is divisible by 3
$ cargo run Compiling branches v0.1.0 (file:///projects/branches) Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.30s Running `target/debug/branches` The value of number is: 5
前面提到过代码块的值就是代码块中最后一个表达式的值,数字本身也是表达式。在这个例子中整个 if 表达式的值是由执行哪段代码块而决定的,也就意味着 if arm 和 else arm 的值类型必须一致,否则会报错。
1 2 3 4 5 6 7
fnmain() { letcondition = true;
letnumber = if condition { 5 } else { "six" };
println!("The value of number is: {number}"); }
当我们编译这段代码,会报错:
1 2 3 4 5 6 7 8 9 10 11 12
$ cargo run Compiling branches v0.1.0 (file:///projects/branches) error[E0308]: `if` and `else` have incompatible types --> src/main.rs:4:44 | 4 | let number = if condition { 5 } else { "six" }; | - ^^^^^ expected integer, found `&str` | | | expected because of this
For more information about this error, try `rustc --explain E0308`. error: could not compile `branches` (bin "branches") due to 1 previous error
类型不一致会报错,因为编译器没法提前知道 number 的类型,进而不能对 number 的使用做检查了。
我们写程序时经常会出现需要在循环体中判断一个条件,如果条件成立则继续执行循环,否则结束循环。我们可以使用 loop、if、else 和 break 来实现这样的逻辑。但是由于这个模式太过于场景,于是在 Rust 中就提供了一个内建的结构来实现。这就是 while 循环。
1 2 3 4 5 6 7 8 9 10 11
fnmain() { letmut number = 3;
while number != 0 { println!("{number}!");
number -= 1; }
println!("LIFTOFF!!!"); }
使用 while 循环就消除了一些不必要的 if 和 else 使得程序更加的清晰。
使用 for 循环遍历集合
使用 while 循环可以实现遍历一个集合中的每一个元素,例如数组。
1 2 3 4 5 6 7 8 9 10
fnmain() { leta = [10, 20, 30, 40, 50]; letmut index = 0;
while index < 5 { println!("the value is: {}", a[index]);
index += 1; } }
这段代码中会每次将 index 加一作为索引并使用它去访问数组,直到索引超出数组有效范围:
1 2 3 4 5 6 7 8 9
$ cargo run Compiling loops v0.1.0 (file:///projects/loops) Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.32s Running `target/debug/loops` the value is: 10 the value is: 20 the value is: 30 the value is: 40 the value is: 50
但是,这样很容易出错,比如我们修改了数组长度,也需要同时修改循环的判断条件。一种更加简介的代替方式是使用 for 循环:
1 2 3 4 5 6 7
fnmain() { leta = [10, 20, 30, 40, 50];
forelementin a { println!("the value is: {element}"); } }