跟着谷歌安卓团队学Rust - 强大的matching表达式

167 阅读4分钟

大家好,我是梦兽编程。欢迎回来与梦兽编程一起刷Rust的系列。

这是由 Google 的 Android开发团队的分享Rust课程。本课程涵盖了 Rust 的方方面面,从基本语法到泛型和错误处理等高级主题。

该课程的最新版本可以在 google.github.io/comprehensi…找到。如果您正在其他地方阅读,请检查那里的更新。

如果你喜欢看梦兽编程的版本可以订阅跟着谷歌安卓团队学Rust订阅最新内容,梦兽编程也期待大家关注我的个人网站。

加入梦兽编程微信群个人掘金主页点击沸点扫描进入,活体咨询师

Match

在之前的分享里有提过Match关键词,rust语言没有给我们提供switch的关键词的功能,但是提供类似switch的功能match。

match可以让你值进行与一个模式或者多个模式进行匹配,从从上到下进行查询,知道找到匹配规则为止。而且这种匹配规则可以是很随意,总之比switch强大就对了。

n main() {
    let input = 'x';
    match input {
        'q'                       => println!("Quitting"),
        'a' | 's' | 'w' | 'd'     => println!("Moving around"),
        '0'..='9'                 => println!("Number input"),
        key if key.is_lowercase() => println!("Lowercase: {key}"),
        _                         => println!("Something else"),
    }
}

match 是一种强大的控制结构,用于将一个值与一系列模式进行匹配,并根据匹配的模式执行相应的代码。通过 match,您可以根据不同的情况执行不同的操作,这在处理枚举、结构体、引用和其他类型时非常有用。

在rust中_ 模式是匹配任何值的通配符模式。 这些表达式必须是无可辩驳的,这意味着它涵盖了所有可能性,因此 _ 通常用作最终的包罗万象的情况。

如果上面的例子,如果我们在其他语言实现大概如下吧。

switch(input){
case `q`:
	break;
case `a`:
case `s`:
case `w`:
case `d`:
	break;
case 0:
case 1:
case 2:
case 3:
case 4:
//...
break;
// 上面rust中的第四点是无法实现的
}

是不是感觉match表达式使用起来简洁许多?

Match在枚举中的使用

如果有使用typescript开发经验的同学应该使用过枚举这一个类型。

enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter,
}

以上代码中很多语言都会默认给第一个成员变量添加一个默认值,在你不填写的时候它默认为0,以此累积增加。

但是在rust枚举默认不会给你添加默认值。这样做的目的为了更好的与其他系统进行对接,还是使用同一份的枚举代码。只是根据不同系统进行match匹配出不同系统的值。

我们需要使用枚举之前定义一个value_in_cents函数进行业务的匹配规则。

enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter,
}

fn value_in_cents(coin: Coin) -> u8 {
    match coin {
        Coin::Penny => {
            println!("Lucky penny!");
            1
        }
        Coin::Nickel => 5,
        Coin::Dime => 10,
        Coin::Quarter => 25,
    }
}

fn main() {
    let coin = Coin::Penny;
    println!("Value in cents: {}", value_in_cents(coin));
}

对处理结构体或者引用类型处理

这是match提供最强大的功能之一,在其他语言可能你需要做很多处理才能实现以下功能。在match表达式下会帮你省去很多不必要的代码与设计模式。

struct Person {
    name: String,
    age: u32,
}

fn print_person_info(person: &Person) {
    match person {
        // 匹配姓名为 "Alice" 的人
        &Person { name, .. } if name == "Alice" => {
            println!("Hello, Alice!");
        }
        // 匹配年龄小于 18 岁的人
        &Person { age, .. } if age < 18 => {
            println!("You are underage.");
        }
        // 匹配其他人
        &Person { name, age } => {
            println!("Name: {}, Age: {}", name, age);
        }
    }
}

fn main() {
    let alice = Person {
        name: String::from("Alice"),
        age: 25,
    };
    let bob = Person {
        name: String::from("Bob"),
        age: 16,
    };

    print_person_info(&alice);
    print_person_info(&bob);
}

在这个示例中,我们定义了一个 Person 结构体,它有 name 和 age 两个字段。

print_person_info 函数接受一个 Person 的引用作为参数,并使用 match 匹配不同的引用模式。

第一个模式匹配的是姓名为 "Alice" 的人,它打印出 "Hello, Alice!"。 第二个模式匹配的是年龄小于 18 岁的人,它打印出 "You are underage"。 第三个模式匹配的是其他人,它打印出姓名和年龄。 在 main 函数中,我们创建了两个不同的 Person 实例,并依次调用 print_person_info 函数来输出它们的信息。

通过使用 match 匹配引用的不同值,我们可以根据引用的内容执行不同的操作。这对于处理引用类型的函数参数非常有用,可以根据不同的情况执行相应的逻辑。

通过这种match方式我们可以省去编写难于阅读的策略者模式产生的多余代码。

总结

match是一个比switch给强大的表达式,如果你正在参试使用rust,不妨试试使用match来解决策略者模式或者callback带来代码阅读不清晰地方。

rexweb.link/category/te…或者更多技术可以收藏梦兽编程rexweb.link

  1. 梦兽编程倔强号
  2. 梦兽编程知乎
  3. 梦兽编程bilibili

微信搜索梦兽编程公众号,发送111即可加入交流群与梦兽编程一起交流。