深入理解Rust的模式匹配

news2024/11/24 3:18:04

文章目录

    • 基础用法
      • 匹配各种类型
      • 模式匹配赋值
      • 提取绑定值
      • 解构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.coloradmin.cn/o/2246400.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【YOLOv8】安卓端部署-1-项目介绍

【YOLOv8】安卓端部署-1-项目介绍 1 什么是YOLOv81.1 YOLOv8 的主要特性1.2 YOLOv8分割模型1.2.1 YOLACT实例分割算法之计算掩码1.2.1.1 YOLACT 的掩码原型与最终的掩码的关系1.2.1.2 插值时的目标检测中提取的物体特征1.2.1.3 coefficients&#xff08;系数&#xff09;作用1.…

基于Spring Boot+Unipp的博物馆预约小程序(协同过滤算法、二维码识别)【原创】

&#x1f388;系统亮点&#xff1a;协同过滤算法、二维码识别&#xff1b; 一.系统开发工具与环境搭建 1.系统设计开发工具 后端使用Java编程语言的Spring boot框架 项目架构&#xff1a;B/S架构 运行环境&#xff1a;win10/win11、jdk17 前端&#xff1a; 技术&#xff1a;框…

Spring Boot 3 【八】整合实现高可用 Redis 集群

一、引言 在当今快速发展的软件开发领域&#xff0c;系统的性能和可靠性至关重要。Springboot 3 整合 Redis 7 集群具有多方面的重大意义。 首先&#xff0c;随着业务的不断发展&#xff0c;数据量呈爆炸式增长&#xff0c;单个 Redis 服务器往往难以满足存储和处理需求。Red…

网络安全-企业环境渗透2-wordpress任意文件读FFmpeg任意文件读

一、 实验名称 企业环境渗透2 二、 实验目的 【实验描述】 操作机的操作系统是kali 进入系统后默认是命令行界面 输入startx命令即可打开图形界面。 所有需要用到的信息和工具都放在了/home/Hack 目录下。 本实验的任务是通过外网的两个主机通过代理渗透到内网的两个主机。…

如何创建一个网站?初学者的分步指南

在当今数字化时代&#xff0c;即便你对 Web 开发、设计或编码一窍不通&#xff0c;也能轻松搭建属于自己的网站。无论你是想为个人打造展示平台&#xff0c;还是为企业建立线上形象&#xff0c;只要掌握正确的方法&#xff0c;借助合适的工具与资源&#xff0c;就能在短时间内完…

OceanBase V4.x应用实践:如何排查表被锁问题

DBA在日常工作中常常会面临以下两种常见情况&#xff1a; 业务人员会提出问题&#xff1a;“表被锁了&#xff0c;导致业务受阻&#xff0c;请帮忙解决。” 业务人员还会反馈&#xff1a;“某个程序通常几秒内就能执行完毕&#xff0c;但现在却运行了好几分钟&#xff0c;不清楚…

MongoDB进阶篇-索引(索引概述、索引的类型、索引相关操作、索引的使用)

文章目录 1. 索引概述2. 索引的类型2.1 单字段索引2.2 复合索引2.3 其他索引2.3.1 地理空间索引&#xff08;Geospatial Index&#xff09;2.3.2 文本索引&#xff08;Text Indexes&#xff09;2.3.3 哈希索引&#xff08;Hashed Indexes&#xff09; 3. 索引相关操作3.1 查看索…

Ubuntu20.04 Rk3588 交叉编译ffmpeg7.0

firefly 公司出的rk3588的设备&#xff0c;其中已经安装了gcc 交叉编译工具&#xff0c;系统版本是Ubuntu20.04。 使用Ubuntu20.04 交叉编译ffmpeg_ubuntu下配置ffmpeg交叉编译器为arm-linux-gnueabihf-gcc-CSDN博客文章浏览阅读541次。ubuntu20.04 交叉编译ffmpeg_ubuntu下配…

Java-06 深入浅出 MyBatis - 一对一模型 SqlMapConfig 与 Mapper 详细讲解测试

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 大数据篇正在更新&#xff01;https://blog.csdn.net/w776341482/category_12713819.html 目前已经更新到了&#xff1a; MyBatis&#xff…

Java项目-基于SpringBoot+vue的租房网站设计与实现

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

24.UE5枚举,怪物分类,龙卷风技能

2-26 枚举、怪物分类、龙旋风技能、掉落概率_哔哩哔哩_bilibili 目录 1.枚举 1.1枚举类型的创建 1.2 将枚举类型绑定到怪物蓝图上 1.3枚举类型的使用 1.3.1创建新的掉落物 1.3.2更改怪物掉落逻辑 2.龙卷风技能 2.1输入映射 2.2龙卷风发射物的创建 2.3龙卷风伤害逻辑…

推荐几个 VSCode 流程图工具

Visual Studio Code&#xff08;简称VSCode&#xff09;是一个由微软开发的免费、开源的代码编辑器。 VSCode 发布于 2015 年&#xff0c;而且很快就成为开发者社区中广受欢迎的开发工具。 VSCode 可用于 Windows、macOS 和 Linux 等操作系统。 VSCode 拥有一个庞大的扩展市…

解决 VMware 嵌套虚拟化提示 关闭“侧通道缓解“

最近给电脑做了新版的 Windows 11 LTSC操作系统&#xff0c;在启动VMware Workstation时&#xff0c;提示"此虚拟机已启用侧通道缓解&#xff0c;可增强安全性&#xff0c;但也会降低性能"&#xff0c;但是我没有启用 Hyper-V 相关的任何功能以及 WSL&#xff0c; 从…

Flume日志采集系统的部署,实现flume负载均衡,flume故障恢复

目录 安装包 flume的部署 负载均衡测试 故障恢复 安装包 在这里给大家准备好了flume的安装包 通过网盘分享的文件&#xff1a;apache-flume-1.9.0-bin.tar.gz 链接: https://pan.baidu.com/s/1DXMA4PxdDtUQeMB4J62xoQ 提取码: euz7 --来自百度网盘超级会员v4的分享 ----…

P2TR(Taproot 交易)和Musig2

目录 P2TR(Taproot 交易)和Musig2 P2TR(Taproot 交易) Musig2 总结 P2TR(Taproot 交易)和Musig2 都是比特币和区块链技术中的先进功能,它们各自具有独特的特点和应用场景。以下是两者的区别及举例说明: P2TR(Taproot 交易) 定义: P2TR是一种比特币交易类型,旨…

Web 入门

HTTP 一、概念 Hyper Text Transfer Protocol&#xff0c;超文本传输协议&#xff0c;规定了浏览器和服务器之间数据传输的规则。 二、特点 基于TCP协议&#xff1a;面向连接&#xff0c;安全。基于请求-响应模型的&#xff1a;一次请求对应一次响应。HTTP协议是无状态的协…

Docker+Nginx | Docker(Nginx) + Docker(fastapi)反向代理

在DockerHub搜 nginx&#xff0c;第一个就是官方镜像库&#xff0c;这里使用1.27.2版本演示 1.下载镜像 docker pull nginx:1.27.2 2.测试运行 docker run --name nginx -p 9090:80 -d nginx:1.27.2 这里绑定了宿主机的9090端口&#xff0c;只要访问宿主机的9090端口&#…

Postman之变量操作

系列文章目录 1.Postman之安装及汉化基本使用介绍 2.Postman之变量操作 3.Postman之数据提取 4.Postman之pm.test断言操作 5.Postman之newman Postman之变量操作 1.pm.globals全局变量2.pm.environment环境变量3.pm.collectionVariables集合变量4.pm.variables5.提取数据-设置变…

鸿蒙动画开发08——帧动画

1、概 述 帧动画通过应用onFrame逐帧回调的方式&#xff0c;让开发者在应用侧的每一帧都可以设置属性值&#xff0c;从而实现设置了该属性值对应组件的动画效果。 相比于属性动画&#xff0c;开发者可感知动画的过程&#xff0c;实时修改UI侧的值&#xff0c;具有事件可实时响…

《Python基础》之字符串格式化输出

目录 方式一 1、带索引 {0} 2、不带索引 { } 3、{自定义变量} 方式二 方式三 控制浮点数精度 方式一 使用.format( )进行格式化 1、带索引 {0} name boy age 18 high 183.55555 gender man print(姓名是&#xff1a;{0},年龄是:{1},身高是:{2},性别是:{3},身高是…