当前位置: 首页 > article >正文

深入理解Rust的模式匹配

文章目录

    • 基础用法
      • 匹配各种类型
      • 模式匹配赋值
      • 提取绑定值
      • 解构Option
    • 高级用法
      • 添加匹配守卫
      • 范围匹配
      • 切片模式
      • 变量绑定
      • 使用..进行模糊匹配
      • 使用_进行值忽略
      • 固定某个字段的匹配
      • 多分支匹配
    • 其它匹配方式
      • if let匹配方式
      • 使用matches!宏进行匹配

在Rust编程语言中,模式匹配是一种非常强大的功能,它允许开发者以灵活和表达性强的方式处理值。这是通过使用match语句和模式来实现的,它类似于其他语言中的switch语句,但提供了更多的灵活性和安全性。

基础用法

在Rust中match语句允许你将一个值与一系列模式进行比较,并根据匹配到的模式执行相应的代码块。
Rust的模式匹配支持多种不同的模式类型,包括:
1.字面值: 匹配具体的数值或者布尔值等。
2.绑定: 通过模式将值绑定到变量。
3.元组和结构体: 可以对元组或结构体的具体结构进行模式匹配。
4.枚举: 匹配枚举的不同变体。
5.引用: 匹配引用,包括通过解引用进行匹配。
6.范围: 匹配一个范围内的值,例如 1…=5 表示从 1 到 5 的所有值。

匹配各种类型

Rust中match语法的调用模版如下:

//语法结构
match target {
    模式1 => 表达式1,
    模式2 => {
        语句1;
        语句2;
        表达式2
    },
    _ => 表达式3
}

匹配字面值

//匹配字面值   
let x = 3;
match x {
    1 => println!("one"),
    2 => println!("two"),
    3 => println!("three"),
    //_用与匹配其它的参数 类似于C++的default  
    _ => println!("anything"),
}

匹配枚举值

//匹配枚举类型  
enum Direction {
    East,
    West,
    North,
    South,
}

fn main() {
    let dire = Direction::South;
    match dire {
        Direction::East => println!("East"),
        //匹配North 或 South  
        Direction::North | Direction::South => {
            println!("South or North");
        },
        //匹配剩余的其它类型  
        //除了_通配符,用一个变量来承载其他情况也是可以的
        //other => println!("other direction: {:?}", other),
        _ => println!("West"),
        //_ =>() 空操作
    };
}

匹配结构体

struct Point {
    x: i32,
    y: i32,
}

let point = Point { x: 0, y: 7 };

match point {
    Point { x, y: 0 } => println!("On the x axis at {}", x),
    Point { x: 0, y } => println!("On the y axis at {}", y),
    Point { x, y } => println!("On neither axis: ({}, {})", x, y),
}

匹配嵌套的结构体和枚举

enum Color {
   Rgb(i32, i32, i32),
   Hsv(i32, i32, i32),
}
enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(Color),
}

fn main() {
    let msg = Message::ChangeColor(Color::Hsv(0, 160, 255));
    match msg {
        Message::ChangeColor(Color::Rgb(r, g, b)) => {
        }
        Message::ChangeColor(Color::Hsv(h, s, v)) => {
        }
        _ => ()
    }
}

模式匹配赋值

match本身也是一个表达式,除了可以用来处理业务逻辑之外还可以用来赋值。

enum IpAddr {
   Ipv4,
   Ipv6
}
fn main() {
    let ip1 = IpAddr::Ipv6;
    //模式匹配的结果赋值给ip_str
    let ip_str = match ip1 {
        IpAddr::Ipv4 => "127.0.0.1",
        _ => "::1",
    };
    println!("{}", ip_str);
}

提取绑定值

在模式匹配的时候提取枚举中的绑定值。

//提取枚举值中绑定的数据  
enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(i32, i32, i32),
}

fn main() {
    let msg = Message::ChangeColor(0, 160, 255);
    match msg {
        Message::Quit => {
        }
        Message::Move { x, y } => {
        }
        Message::Write(text) => println!("Text message: {}", text),
        Message::ChangeColor(r, g, b) => {
        }
    }
}

解构Option

enum Option<T> {
    None,
    Some(T),
}
fn plus_one(x: Option<i32>) -> Option<i32> {
    match x {
        None => None,
        Some(i) => Some(i + 1),
    }
}
let five = Some(5);
let six = plus_one(five);
let none = plus_one(None);

高级用法

添加匹配守卫

match语句的模式可以包含守卫(guard),增加则外的条件判断,用于在模式匹配后进一步确定是否执行对应的代码块。

let num = Some(4);
match num {
    //Some(x) 且x<5执行该语句  x<5就是匹配守卫 进行额外的条件判断  
    Some(x) if x < 5 => println!("less than five"),
    Some(x) => println!("greater than or equal to five"),
    None => (),
}

范围匹配

不用一个一个写对应的匹配值,直接匹配一定范围内的值。通过序列 …= 匹配值的范围

//匹配1--5  
let x = 5;
match x {
    1..=5 => println!("one through five"),
    _ => println!("something else"),
}

//匹配a--j  k--z  
let x = 'c';
match x {
    'a'..='j' => println!("early ASCII letter"),
    'k'..='z' => println!("late ASCII letter"),
    _ => println!("something else"),
}

切片模式

Rust的模式匹配还可以应用于数组和切片,这使得处理数据序列时更加灵活

let arr = [1, 2, 3];
match arr {
    //匹配以1开头的数组  
    [1, _, _] => println!("Starts with one"),
    //匹配以2为中间值的数组 
    [_, 2, _] => println!("Contains two in the middle"),
    //匹配以3结尾的数组 
    [_, _, 3] => println!("Ends with three"),
    //匹配其它值  
    _ => println!("Does not match any pattern"),
}

变量绑定

Rust的模式匹配还支持使用@进行绑定,这允许在进行模式匹配的同时,将匹配的值绑定到变量上.

//当你既想要限定分支范围,又想要使用分支的变量时,就可以用 @ 来绑定到一个新的变量上
enum Message {
    Hello { id: i32 },
}
let msg = Message::Hello { id: 5 };
match msg {
    Message::Hello { id: id_variable @ 3..=7 } => {
        println!("Found an id in range: {}", id_variable)
    },
    Message::Hello { id: 10..=12 } => {
        println!("Found an id in another range")
    },
    Message::Hello { id } => {
        println!("Found some other id: {}", id)
    },
}

使用…进行模糊匹配

//用 .. 忽略剩余值
struct Point {
    x: i32,
    y: i32,
    z: i32,
}
let origin = Point { x: 0, y: 0, z: 0 };
match origin {
    //不关心后续的值 只匹配第一个值
    Point { x, .. } => println!("x is {}", x),
}

使用_进行值忽略

//使用_忽略整个值  忽略第一个参数  只使用第二个参数 
fn foo(_: i32, y: i32) {
    println!("This code only uses the y parameter: {}", y);
}
fn main() {
    foo(3, 4);
}

//使用嵌套的_忽略部分值
let mut setting_value = Some(5);
let new_setting_value = Some(10);

match (setting_value, new_setting_value) {
    //忽略绑定值 不进行操作  
    (Some(_), Some(_)) => {
        println!("Can't overwrite an existing customized value");
    }
    _ => {
        setting_value = new_setting_value;
    }
}

//忽略特定位置的值,只操作未被忽略的值  
let numbers = (2, 4, 8, 16, 32);
match numbers {
    (first, _, third, _, fifth) => {
        println!("Some numbers: {}, {}, {}", first, third, fifth)
    },
}

//使用下划线开头表示未使用的变量
//只使用_和使用以下划线开头的名称有些微妙的不同: 比如_x仍会将值绑定到变量,而_则完全不会绑定。
fn main() {
    let _x = 5;
    let y = 10;
}

固定某个字段的匹配

//固定某个字段的匹配模式
fn main() {
    let p = Point { x: 0, y: 7 };
    match p {
        //y=0 的匹配  
        Point { x, y: 0 } => println!("On the x axis at {}", x),
        //x=0 的匹配  
        Point { x: 0, y } => println!("On the y axis at {}", y),
        Point { x, y } => println!("On neither axis: ({}, {})", x, y),
    }
}

多分支匹配

增加了逻辑或操作,一个语句里面匹配多个条件

//多分支匹配 
let x = 1;
match x {
    1 | 2 => println!("one or two"),
    3 => println!("three"),
    _ => println!("anything"),
}

其它匹配方式

if let匹配方式

当你只要匹配一个条件,且忽略其他条件时就用if let ,否则都用match

let v = Some(3u8);
match v {
    Some(3) => println!("three"),
    _ => (),
}
//等价于
if let Some(3) = v {
    println!("three");
}

使用matches!宏进行匹配

enum MyEnum {
    Foo,
    Bar
}
fn main() {
    let v = vec![MyEnum::Foo,MyEnum::Bar,MyEnum::Foo];
    //过滤Foo 
    v.iter().filter(|x| matches!(x, MyEnum::Foo));
    //其它匹配方式
    let foo = 'f';
    assert!(matches!(foo, 'A'..='Z' | 'a'..='z'));
    let bar = Some(4);
    assert!(matches!(bar, Some(x) if x > 2));
}

http://www.kler.cn/a/406982.html

相关文章:

  • 主IP地址与从IP地址:深入解析与应用探讨
  • 人工智能(AI)与机器学习(ML)基础知识
  • java-贪心算法
  • 嵌入式面试八股文(九)·FreeRTOS与Linux的区别与相同点、多进程与多线程的区别、为什么项目使用多线程
  • 什么是Hadoop
  • 如何在Word文件中设置水印以及如何禁止修改水印
  • qt 发布简单项目
  • 【项目日记】仿mudou的高并发服务器 --- 实现缓冲区模块,通用类型Any模块,套接字模块
  • IDEA中Spring Initializr jdk1.8 没有Java8选项问题处理办法
  • JavaScript的类型转换
  • 第二十六章 TCP 客户端 服务器通信 - $ZB 和 READ 命令
  • goframe开发一个企业网站 MongoDB 完整工具包19
  • c#:winform调用bartender实现打印(学习整理笔记)
  • 使用IDEA构建springboot项目+整合Mybatis
  • Redis相关面试题汇总
  • HARCT 2025 新增分论坛7:机器人和自动化的新趋势
  • CMake笔记:install(TARGETS target,...)无法安装的Debug/lib下
  • 常见LLM大模型概览与详解
  • 【AI日记】24.11.23 学习谷歌数据分析初级课程-第4课
  • linux通过手工删除文件卸载oracle 11g rac的具体步骤
  • Springboot项目搭建(4)-文章管理接口
  • 《操作系统 - 清华大学》4 -5:非连续内存分配:页表一反向页表
  • 3D可视化引擎HOOPS Luminate场景图详解:形状的创建、销毁与管理
  • python安装包中的一些问题(一):conda list 已经安装的包为啥在spyder pip list中没有?
  • 从监控异常发现网络安全
  • Exploring Prompt Engineering: A Systematic Review with SWOT Analysis