7、初识Rust – 控制流

目录 编程

控制流是大部分编程语言的基本组成部分。Rust代码中最常见的控制程序执行流的结构就是 if 表达式和循环。

一、if表达式

if表达式根据条件来执行不同的代码分支,代码中的条件必须是 bool 值。如果不是bool值,Rust就会抛出错误。这和部分编程语言,比如javascript不一样,Rust不会尝试将非bool值转换为bool值。

fn main() {
     let a = 2;
     if a > 1 {
         println!(">1");
     } else {
         println!("<1");
     }
}

例如上面这段代码,条件检查变量a是否大于1,如果大于1就执行紧跟在条件后的表达式打印 “>1” 如果小于1,就执行else后的表达式打印 “<1″。esle表达式用来提供条件为假时执行的代码块。

Rust可以和大多数编程语言一样,使用else if表达式与if else表达式实现多重条件。

fn main() {
    let a = 4;

    if a == 1 {
         println!("a等于1");
    } else if a == 2 {
         println!("a等于2");
    } else if a == 3 {
         println!("a等于3");
    } else {
         println!("a不等于1,2,3");
    }

}

例如上面这段代码,它按顺序检查每个 if 表达式并执行第一个条件为真的代码块。一旦找到为真的代码块后,就不会在检查后续的代码块。

前面说到if与else都是一个表达式,所以我们可以在let中使用它并获得返回值。

fn main() {
   let a = 1;
   let b = if a > 1 {
       3
   } else {
       4
   }
   println!("{b}");
}

但是要特别注意,返回值类型需要相同,否则就会抛出错误。

二、循环

在实际应用中,多次执行同一段代码的需求非常常见。Rust提供了多种循环。

Rust有三种循环,分别是 loop、while、for。

1、loop

loop循环告诉Rust,一直循环一段代码,直到你发出停止指令。

fn main() {
    loop {
         println!("loop");
    }
}

上面这个例子,就会无限打印 loop直到你手动(ctrl-c)结束。

当然,Rust也提供了手动结束loop循环的命令。

fn main() {
    let mut i = 0;
    loop {
        if i == 10 {
             println!("{i}");
             break;
        }else{
             println!("{i}");
             i = i + 1;
        }
    }
}

上面这个例子,就是loop循环,并在每次循环时对i进行判断,如果没有等于10,那么就对i进行一个递增操作,如果等于10那么就使用break跳出loop循环。

fn main() {
     let mut a = 0;
     loop {
          if a == 10 {
               println!("{a}");
               continue;
          } else {
               println!("{a}");
               a = a + 1;
          }
    }
}

上面这个例子,在循环递增a后,如果判断a == 10,则使用continue跳过该次循环,进行下一次循环。如果你运行上面这段代码,你就会发现,输出0 – 9后,接下去就会无限打印 10。

loop其中一个用法是检查可能会失败的操作,比如检查线程是否完成了任务,这种情况下,你可能需要将结果传递给其它代码。这时就可以将值放在表达式break后面即可。

fn main() {
    let mut a = 0;
    let b = loop {
         if a == 10 {
              break a * 10;
         } else {
              a = a + 1;
         }
    };
    println!("{b}");
}

要注意的是,这次的返回需要加上分号。

除了单层的loop外,我们也可以进行多层嵌套。

fn main() {
    let mut a = 0;
    'test: loop {
        let mut b = 0;
        println!("a: {a}");
        loop {
            if b == 5 {
                println!("b: {b}");
                break;
            }
            if a == 3 {
                break 'test;
            }
            b = b + 1;
        }

        a = a + 1;
    }
    println!("结束 a: {a}");
}

a: 0
b: 5
a: 1
b: 5
a: 2
b: 5
a: 3
结束 a: 3

需要注意的是,如果是嵌套循环,break与continue应该在最内层的循环。我们可以手动指定一个循环标签,例如上面代码中的 ‘test,然后将标签与 break 和 continue一起使用。使这些关键字应用对相对层的loop 生效,而不是最内层。

2、while条件循环

while条件循环可以判断条件是否满足,条件为false时停止循环,条件为true时继续循环。这个功能使用loop + if + else表达式也可以实现,但是复杂度会提升不少,所以就有了while这个循环。

fn main() {
    let mut a = 10;

   while a != 0 {
       println!("{a}");
       a = a - 1;
   };
   println!("完成!");
}

10
9
8
7
6
5
4
3
2
1
完成!

这种结构消除了很多使用 loopifelse 和 break 时所必须的嵌套,这样更加清晰。当条件为真就执行,否则退出循环。可以使用while来遍历集合中的元素,比如数组。

fn main() {
    let a = [1; 10];
    let mut index = a.len() - 1;

   while index != 0 {
       println!("{}",a[index]);
       index = index - 1;
   };
   println!("完成!");
}

不过这个过程会使程序运行变慢,同时也不够简洁。for是更简洁的一个替换方案。

3、for循环

前面说到for在遍历元素时时while一个非常好的替换方案。

fn main() {
    let a = [1; 10];

    for ele in a {
        println!("{ele}")
    }

    println!("完成!");
}

如上面代码,可以遍历a数组并将每个值输出。for循环的安全性和简洁性使它成为了Rust中使用最多的循环结构,即使想要循环执行代码特定次数时,也会使用for循环,如下程序。

fn main() {
    for i in {1..16}.rev() {
        println!("{i}")
    }

    println!("完成!");
}