» Rust快速入门 » 1. 基础篇 » 1.8 控制流

控制流

在大多数编程语言中,根据条件是否为 true 执行一些代码以及在条件为 true 时重复执行一些代码的能力是大多数编程语言的构建基石。

If Else

fn main() {
    let a = 58;
    if a < 0 {
        print!("{} is negative", a); 
    } else if a > 0 {
        print!("{} is positive", a);
    } else {
        print!("{} is zero", a);
    }
}

Loop

Rust 提供了 loop 关键字来表示无限循环。与其他类似 C 系语言一样,break 语句可用于在任何时候退出循环,而 continue 语句可用于跳过迭代剩余逻辑并开始新的迭代。

fn main() {
    let mut count = 0;
    loop {
        count += 1;
        if count == 7 {
            println!("seven");
            continue;
        }
        println!("{}", count);
        if count == 10 {
            println!("Let's end here!");
            break;
        }
    }
}

Loop 标签

你可以为循环加上一些 'label 标签。breakcontinue 可以通过标签直接控制外层循环。

fn main() {
    'outer: loop {
        println!("The outer loop begins");
        'inner: loop {
            println!("The inner loop begins");
            break 'outer;
        }
        println!("Unreachable line here");
    }
    println!("The outer loop ends");
}

从循环中返回

你可以在 break 后放置返回值,它将被 loop 表达式直接返回。

fn main() {
    let mut counter = 0;
    let result = loop {
        counter += 1;
        if counter == 10 {
            break counter * 2;
        }
    };
    println!("counter: {} result: {}", counter, result);
    // counter: 10 result: 20
}

While

fn main() {
    let mut n = 1;
    while n < 10 {
        if n % 2 == 0 {
            println!("{}", n);
        }
        n += 1;
    }
}

For

a..b 写法可以在 Rust 中创建区间(range)for ... in 结构可用于遍历区间,或者广义上地,可以遍历迭代器 Iterator

fn main() {
    for n in 1..5 {
        print!("{} ", n); // 1 2 3 4 
    }
}

如果要包含区间的末尾元素,使用 a..=b 写法。

fn main() {
    for n in 1..=5 {
        print!("{} ", n); // 1 2 3 4 5
    }
}

iter, iter_mutinto_iter 分别以不同的方式将集合转换为迭代器。

fn main() {
    let names = vec!["Alice", "Bob", "Cindy"];
    for name in names.iter() {
        print!("{} ", name)
    }
    println!("\nnames: {:?}", names);
    // Alice Bob Cindy 
    // names: ["Alice", "Bob", "Cindy"]
}

Match

模式匹配类似 C switch 语句,但它更强悍一些。

fn main() {
    let number = 7;
    match number {
        1 => println!("One"),
        2 | 3 | 5 | 7 | 11 => println!("A prime"),
        13..=19 => println!("A teen"),
        _ => println!("Others"),
    }
}

解构

match 块可以用各种方式解构项(元组、数组、枚举、结构体等等)。

fn main() {
    let triple = (5, -8, 2);
    match triple {
        (0, y, z) => println!("First is `0`, `y` is {:?}, and `z` is {:?}", y, z),
        (1, ..)  => println!("First is `1` and the rest doesn't matter"),
        (.., 2)  => println!("last is `2` and the rest doesn't matter"),
        _      => println!("It doesn't matter what they are"),
    }
    // last is `2` and the rest doesn't matter
}
enum Color {
    Red,
    RGB(u16, u16, u16),
    CMYK(u32, u32, u32, u32),
}

fn main() {
    let color = Color::RGB(58, 23, 78);
    match color {
        Color::Red   => println!("The color is Red!"),
        Color::RGB(r, g, b) =>
            println!(
                "Red: {}, green: {}, and blue: {}", r, g, b),
        Color::CMYK(c, m, y, k) =>
            println!(
                "Cyan: {}, magenta: {}, yellow: {}, key (black): {}!",
                c, m, y, k),
    }
    // Red: 58, green: 23, and blue: 78
}

Guard(卫语句)

卫语句 可以为匹配分支添加过滤条件。

fn main() {
    let a: u8 = 58;

    match a {
        i if i == 0 => println!("Zero"),
        i if i > 0 => println!("Greater than zero"),
        _ => unreachable!("Should never happen."),
    }
    // Greater than zero
}

绑定

match 提供了 @ 符号将值绑定到名称,这样你就可以在分支中将匹配的项作为变量使用。

fn main() {
    let number = 11;
    match number {
        1 => println!("One"),
        n @ (2 | 3 | 5 | 7 | 11) => println!("A prime: {}", n),
        13..=19 => println!("A teen"),
        _ => println!("Others"),
    }
    // A prime: 11
}

If Let

某些用例下,match 匹配略显繁琐。

let a = Some(58);
match a {
    Some(b) => {
        println!("My precious value is {}", b);
    },
    _ => {},
}

if let 在这种用例下显得更加简洁。

if let Some(b) = a {
    println!("My value is {}", b);
}

While Let

while let 可以处理类似的用例。

fn main() {
    let mut optional = Some(0);
    while let Some(i) = optional {
        if i > 9 {
            println!("Hit 9, quit!");
            optional = None;
        } else {
            println!("It's {}, try again.", i);
            optional = Some(i + 1);
        }
    }
}
// It's 0, try again.
// It's 1, try again.
// It's 2, try again.
// It's 3, try again.
// It's 4, try again.
// It's 5, try again.
// It's 6, try again.
// It's 7, try again.
// It's 8, try again.
// It's 9, try again.
// Hit 9, quit!

代码挑战

尝试修改编辑器中提供的代码,使其打印 Greeting from John: John

Loading...
> 此处输出代码运行结果
上页
下页