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

掌握Rust模式匹配:从基础语法到实际应用

本篇文章将探讨 Rust 编程语言中至关重要的特性之一——模式匹配。Rust 语言的模式匹配功能强大,不仅能处理简单的值匹配,还能解构和操作复杂的数据结构。通过深入学习模式匹配,程序员可以更加高效地编写出清晰、简洁且易于维护的代码。

Rust 语言中的模式匹配是一种特殊的语法结构,用于匹配变量、解构数组、结构体、枚举和元组等。本文主要介绍了 Rust 中各种模式的使用场景,包括 match、if let、while let、for 循环以及函数参数。除了基础语法外,还讲解了可辩驳性和无可辩驳性、字面值匹配、命名变量、多重模式、范围匹配、结构解构等模式的使用细节。

模式

  • 模式是Rust中的一种特殊语法,用于匹配复杂和简单类型的结构
  • 将模式与匹配表达式和其他构造结合使用,可以更好地控制程序的控制流
  • 模式由以下元素(的一些组合)组成:
    • 字面值
    • 解构的数组、enum、struct 和 tuple
    • 变量
    • 通配符
    • 占位符
  • 想要使用模式,需要将其与某个值进行比较:
    • 如果模式匹配,就可以在代码中使用这个值的相应部分

一、用到模式(匹配)的地方

match 的 Arm

match VALUE {PATTERN => EXPRESSION,PATTERN => EXPRESSION,PATTERN => EXPRESSION,
}
  • match 表达式的要求:
    • 详尽(包含所有的可能性)
  • 一个特殊的模式:_(下划线):
    • 它会匹配任何东西
    • 不会绑定到变量
    • 通常用于 match 的最后一个 arm;或用于忽略某些值。

条件 if let 表达式

  • if let 表达式主要是作为一种简短的方式来等价的代替只有一个匹配项的 match
  • if let 可选的可以拥有 else,包括:
    • else if
    • else if let
  • 但,if let 不会检查穷尽性
fn main() {let favorite_color: Option<&str> = None;let is_tuesday = false;let age: Result<u8, _> = "34".parse();if let Some(color) = favorite_color {println!("Using your favorite color, {}, as the background", color);} else if if_tuesday {println!("Tuesday is green day!");} else if let Ok(age) = age {if age > 30 {println!("Using purple as the background color");} else {println!("Using orange as the background color");}} else {println!("Using blue as the background color");}
}

While let 条件循环

  • 只要模式继续满足匹配的条件,那它允许 while 循环一直运行
fn main() {let mut stack = Vec::new();stack.push(1);stack.push(2);stack.push(3);while let Some(top) = stack.pop() {println!("{}", top);}
}

for 循环

  • for 循环是Rust 中最常见的循环
  • for 循环中,模式就是紧随 for 关键字后的值
fn main() {let v = vec!['a', 'b', 'c'];for (index, value) in v.iter().enumerate() {println!("{} is at index {}", value , index);}
}

Let 语句

  • let 语句也是模式
  • let PATTERN = EXPRESSION
fn main() {let a = 5;let (x, y, z) = (1, 2, 3);let (q, w) = (4, 5, 6); // 报错 类型不匹配 3 2
}

函数参数

  • 函数参数也可以是模式
fn foo(x: i32) {// code goes here
}fn print_coordinates(&(x, y): &(i32, i32)) {println!("Current location: ({}, {})", x, y);
}fn main() {let point = (3, 5);print_coordinates(&point);
}

二、可辩驳性:模式是否会无法匹配

模式的两种形式

  • 模式有两种形式:可辨驳的、无可辩驳的
  • 能匹配任何可能传递的值的模式:无可辩驳的
    • 例如:let x = 5;
  • 对某些可能得值,无法进行匹配的模式:可辩驳的
    • 例如:if let Some(x) = a_value
  • 函数参数、let 语句、for 循环只接受无可辩驳的模式
  • if let 和 while let 接受可辨驳和无可辩驳的模式
fn main() {let a: Option<i32> = Some(5);let Some(x) = a: // 报错 Noneif let Some(x) = a {}if let x = 5 {} // 警告
}

三、模式语法

匹配字面值

  • 模式可直接匹配字面值
fn main() {let x = 1;match x {1 => println!("one"),2 => println!("two"),3 => println!("three"),_ => println!("anything"),}
}

匹配命名变量

  • 命名的变量是可匹配任何值的无可辩驳模式
fn main() {let x = Some(5);let y = 10;match x {Some(50) => println!("Got 50"),Some(y) => println!("Matched, y = {:?}", y),_ => println!("Default case, x = {:?}", x),}println!("at the end: x = {:?}, y = {:?}", x, y);
}

多重模式

  • 在match 表达式中,使用 | 语法(就是或的意思),可以匹配多种模式
fn main() {let x = 1;match x {1 | 2 => println!("one or two"),3 => println!("three"),_ => println!("anything"),}
}

使用 ..= 来匹配某个范围的值

fn main() {let x = 5;match x {1..=5 => println!("one through five"),_ => println!("something else"),}let x = 'c';match x {'a' ..='j' => println!("early ASCII letter"),'k' ..='z' => println!("late ASCII letter"),_ => println!("something else"),}
}

解构以分解值

  • 可以使用模式来解构 struct、enum、tuple,从而引用这些类型值的不同部分
struct Point {x: i32,y: i32,
}fn main() {let p = Point { x: 0, y: 7 };let Point { x: a, y: b } = p;assert_eq!(0, a);assert_eq!(7, b);let Point {x, y} = p;assert_eq!(0, x);assert_eq!(7, y);match p {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

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 => {println!("The Quit variant has no data to destructure.")}Message::Move {x, y} => {println!("Move in the x direction {} and in the y direction {}", x, y);}Message::Write(text) => println!("Text message: {}", text),Message::ChangeColor(r, g, b) => {println!("Change the color to red {}, green {}, and blue {}", r, g, b);}}
}

解构嵌套的 struct 和 enum

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::ChangeClolr(Color::Rgb(r, g, b)) => {println!("Change the color to red {}, green {}, and blur {}", r, g, b)}Message::ChangeColor(Color::Hsv(h, s, v)) => {println!("Change the color to hue {}, saturation {}, and value {}", h, s, v)}_ => (),}
}

解构 struct 和 tuple

struct Point {x: i32,y: i32,
}fn main() {let ((feet, inches), Point {x, y}) = ((3, 10), Point {x: 3, y: -10});
}

在模式中忽略值

  • 有几种方式可以在模式中忽略整个值或部分值:
    • _
    • _ 配合其它模式
    • 使用以 _ 开头的名称
    • .. (忽略值的剩余部分)

使用 _ 来忽略整个值

fn foo(_: i32, y: i32) {println!("This code only uses the y parameter: {}", y);
}fn main() {foo(3, 4);
}

使用嵌套的 _ 来忽略值的一部分

fn main() {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;}}println!("setting is {:?}", setting_value);let numbers = (2, 4, 6, 8, 16, 32);match numbers {(first, _, third, _, fifth) => {println!("Some numbers: {}, {}, {}", first, third, fifth)}}
}

通过使用 _ 开头命名来忽略未使用的变量

fn main() {let _x = 5;let y = 10;  // 创建未使用 警告let s = Some(String::from("Hello"));if let Some(_s) = s { // if let Some(_) = s {println!("found a string");}println!("{:?}", s); // 报错 
}

使用 .. 来忽略值的剩余部分

struct Point {x: i32,y: i32,z: i32,
}fn main() {let origin = Point {x: 0, y: 0, z: 0};match origin {Point {x, ..} => println!("x is {}", x),}let numbers = (2, 4, 8, 16, 32);match numbers {(first, .., last) => {println!("Some numbers: {}, {}", first, last);}}match numbers {(.., second, ..) => {  // 报错println!("Some numbers: {}", second)},}
}

使用 match 守卫来提供额外的条件

  • match 守卫就是 match arm 模式后额外的 if 条件,想要匹配该条件也必须满足
  • match 守卫适用于比单独的模式更复杂的场景

例子一:

fn main() {let num = Some(4);match num {Some(x) if x < 5 => println!("less than five: {}", x),Some(x) => println!("{}", x),None => (),}
}

例子二:

fn main() {let x = Some(5);let y = 10;match x {Some(50) => println!("Got 50"),Some(n) if n == y => println!("Matched, n = {:?}", n),_ => println!("Default case, x = {:?}", x),}println!("at the end: x = {:?}, y = {:?}", x, y);
}

例子三:

fn main() {let x = 4;let y = false;match x {4 | 5 | 6 if y => println!("yes"),_ => println!("no"),}
}

@绑定

  • @ 符号让我们可以创建一个变量,该变量可以在测试某个值是否与模式匹配的同时保存该值
enum Message {Hello {id: i32},
}fn main() {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)}}
}

总结

模式匹配在 Rust 中是一个灵活而强大的特性,为程序的控制流提供了极大的灵活性。通过使用 match、if let、while let 等语法,程序员可以在匹配结构中定义和解构不同的数据类型,简化代码逻辑。深入理解模式匹配的用法,将帮助开发者编写更具表达力的代码,为 Rust 编程带来新的思路与技巧,更多相关信息,  https://t.me/gtokentool   。

相关文章:

掌握Rust模式匹配:从基础语法到实际应用

本篇文章将探讨 Rust 编程语言中至关重要的特性之一——模式匹配。Rust 语言的模式匹配功能强大&#xff0c;不仅能处理简单的值匹配&#xff0c;还能解构和操作复杂的数据结构。通过深入学习模式匹配&#xff0c;程序员可以更加高效地编写出清晰、简洁且易于维护的代码。 Rus…...

HFSS 3D Layout中Design setting各个选项的解释

从HFSS 3D LAYOUT菜单中&#xff0c;选择Design Settings打开窗口&#xff0c;会有六个选项&#xff1a;DC Extrapolation, Nexxim Options, Export S Parameters, Lossy Dielectrics, HFSS Meshing Method, and HFSS Adaptive Mesh. DC Extrapolation 直流外推 直流外推分为标…...

线性表之链表详解

欢迎来到我的&#xff1a;世界 希望作者的文章对你有所帮助&#xff0c;有不足的地方还请指正&#xff0c;大家一起学习交流 ! 目录 前言线性表的概述链表的概述 内容链表的结构链表节点的定义 链表的基本功能单向链表的初始化链表的插入操作头插操作尾插操作 链表的删除操作头…...

C/C++使用AddressSanitizer检测内存错误

AddressSanitizer 是一种内存错误检测工具&#xff0c;编译时添加 -fsanitizeaddress 选项可以在运行时检测出非法内存访问&#xff0c;当发生段错误时&#xff0c;AddressSanitizer 会输出详细的错误报告&#xff0c;包括出错位置的代码行号和调用栈&#xff0c;有助于快速定位…...

【EI和Scopus检索】国际人工智能创新研讨会(IS-AII 2025)

国际人工智能创新研讨会&#xff08;IS-AII 2025&#xff09;将于2025年1月11日-1月14日在贵阳盛大举行。会议将聚焦计算机科学、人工智能、机器人科学与工程等相关研究领域&#xff0c;广泛邀请国内外知名专家学者&#xff0c;共同探讨相关学科领域的最新发展方向及行业前沿动…...

在OceanBase 中,实现自增列的4种方法

本文作者&#xff1a;杨敬博&#xff0c;爱可生 DBA 团队成员。 背景描述 在OceanBase数据库中&#xff0c;存在MySQL租户与Oracle租户两种模式&#xff0c;本文主要讲解在 OceanBase 的Oracle模式&#xff08;以下简称OB Oracle&#xff09;&#xff0c;创建自增列的4种方式&…...

LWE算法分类及基本加解密算法示例

LWE&#xff08;Learning With Errors&#xff09;算法是一种基于格&#xff08;lattice&#xff09;的密码学原语&#xff0c;广泛应用于构建抗量子计算的加密方案。LWE算法的安全性基于最坏情况下的格问题&#xff08;如最短向量问题SVP和最近向量问题CVP&#xff09;&#x…...

【论文阅读】Learning dynamic alignment via meta-filter for few-shot learning

通过元滤波器学习动态对齐以实现小样本学习 引用&#xff1a;Xu C, Fu Y, Liu C, et al. Learning dynamic alignment via meta-filter for few-shot learning[C]//Proceedings of the IEEE/CVF conference on computer vision and pattern recognition. 2021: 5182-5191. 论文…...

蓝牙 SPP 协议详解及 Android 实现

文章目录 前言一、 什么是蓝牙 SPP 协议&#xff1f;SPP 的适用场景 二、SPP的工作流程1. 蓝牙设备初始化2. 设备发现与配对3. 建立 SPP 连接4. 数据传输5. 关闭连接 三、进阶应用与常见问题蓝牙连接中断与重试机制数据传输中的延迟与错误处理电池消耗和蓝牙优化 总结 前言 蓝…...

系统学习领域驱动设计-感悟-高尚名词篇

高尚名词 高尚名词通俗意思知识消化开发代码过程中的业务理解持续学习团队角度&#xff0c;持续沉淀文档沉淀业务理解&#xff0c;教会更多的新人&#xff0c;不让某些员工掌握知识壁垒...

人工智能(AI)和机器学习(ML)技术学习流程

目录 人工智能(AI)和机器学习(ML)技术 自然语言处理(NLP): Word2Vec: Seq2Seq(Sequence-to-Sequence): Transformer: 范式、架构和自注意力: 多头注意力: 预训练、微调、提示工程和模型压缩: 上下文学习、思维链、全量微调、量化、剪枝: 思维树、思维…...

<Project-20 YT-DLP> 给视频网站下载工具 yt-dlp/yt-dlp 加个页面 python web

介绍 yt-dlp Github 项目&#xff1a;https://github.com/yt-dlp/yt-dlp A feature-rich command-line audio/video downloader 一个功能丰富的视频与音频命令行下载器 原因与功能 之前我用的 cobalt 因为它不再提供Client Web功能&#xff0c;只能去它的官网使用。 翻 redd…...

【Android】Gradle 7.0+ 渠道打包配置

声明 该配置主要解决打包apk/aab需要动态修改渠道字段,方便区分渠道上架国内商店。 暂不支持批量打包(7.4版本无法通过只修改outputFileName的形式批量处理) 因为构建时需要拷贝/创建Output,然后修改outputFileName才能处理批量打包,但拷贝/创建在高版本中失效了。 目前的…...

Web应用性能测试工具 - httpstat

在数字化时代&#xff0c;网站的性能直接影响用户体验和业务成功。你是否曾经在浏览网页时&#xff0c;遇到加载缓慢的困扰&#xff1f;在这个快速变化的互联网环境中&#xff0c;如何快速诊断和优化Web应用的性能呢&#xff1f;今天&#xff0c;我们将探讨一个强大的工具——h…...

MySQL 【流程控制】函数

目录 1、CASE 语句用于流程控制中的多分支情况。 2、IF() 函数根据测试条件是否为真分别返回指定的值。 3、IFNULL() 函数&#xff0c;如果第一个参数为 NULL&#xff0c;返回第二个参数&#xff0c;否则返回第一个参数。 4、NULLIF() 函数根据两个参数是否相等决定返回 NUL…...

python 天气数据可视化

Python爬取天气数据及可视化分析 https://blog.csdn.net/weixin_69423932/article/details/135184643...

【HarmonyOS Next】数据本地存储:@ohos.data.preferences

【HarmonyOS Next】数据本地存储&#xff1a;ohos.data.preferences 在开发现代应用程序时&#xff0c;数据存储是一个至关重要的过程。应用程序为了保持某些用户设置、应用状态以及其他小量数据信息通常需要一个可靠的本地存储解决方案。在 HarmonyOS Next 环境下&#xff0c…...

使用BaGet快速搭建nuget服务

BaGet是基于 asp.net core编写的一个轻量级的 nuget管理服务&#xff0c;安装部署非常简单。 * Nuget版本号规范&#xff1a;https://learn.microsoft.com/zh-cn/nuget/concepts/package-versioning。 环境准备 下载 BaGet安装包。 https://loic-sharma.github.io/BaGet/ 下…...

基于Zynq FPGA的雷龙SD NAND存储芯片性能测试

文章目录 前言一、SD NAND特征1.1 SD卡简介1.2 SD卡Block图 二、SD卡样片三、Zynq测试平台搭建3.1 测试流程3.2 SOC搭建 四、软件搭建五、测试结果六、总结 前言 随着嵌入式系统和物联网设备的快速发展&#xff0c;高效可靠的存储解决方案变得越来越重要。雷龙发展推出的SD NA…...

【功能介绍】信创终端系统上各WPS版本的授权差异

原文链接&#xff1a;【功能介绍】信创终端系统上各WPS版本的授权差异 Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇关于信创终端操作系统上WPS Office各版本&#xff08;不包括政务版、企业版等&#xff09;之间的差异的文章。WPS Office作为国内广泛使用的办公软…...

手游刚开服就被攻击怎么办?如何防御DDoS?

开服初期是手游最脆弱的阶段&#xff0c;极易成为DDoS攻击的目标。一旦遭遇攻击&#xff0c;可能导致服务器瘫痪、玩家流失&#xff0c;甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案&#xff0c;帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

C++实现分布式网络通信框架RPC(3)--rpc调用端

目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中&#xff0c;我们已经大致实现了rpc服务端的各项功能代…...

UE5 学习系列(三)创建和移动物体

这篇博客是该系列的第三篇&#xff0c;是在之前两篇博客的基础上展开&#xff0c;主要介绍如何在操作界面中创建和拖动物体&#xff0c;这篇博客跟随的视频链接如下&#xff1a; B 站视频&#xff1a;s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

【JavaSE】绘图与事件入门学习笔记

-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角&#xff0c;以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向&#xff0c;距离坐标原点x个像素;第二个是y坐标&#xff0c;表示当前位置为垂直方向&#xff0c;距离坐标原点y个像素。 坐标体系-像素 …...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容

目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法&#xff0c;当前调用一个医疗行业的AI识别算法后返回…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

Typeerror: cannot read properties of undefined (reading ‘XXX‘)

最近需要在离线机器上运行软件&#xff0c;所以得把软件用docker打包起来&#xff0c;大部分功能都没问题&#xff0c;出了一个奇怪的事情。同样的代码&#xff0c;在本机上用vscode可以运行起来&#xff0c;但是打包之后在docker里出现了问题。使用的是dialog组件&#xff0c;…...

Selenium常用函数介绍

目录 一&#xff0c;元素定位 1.1 cssSeector 1.2 xpath 二&#xff0c;操作测试对象 三&#xff0c;窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四&#xff0c;弹窗 五&#xff0c;等待 六&#xff0c;导航 七&#xff0c;文件上传 …...

Web后端基础(基础知识)

BS架构&#xff1a;Browser/Server&#xff0c;浏览器/服务器架构模式。客户端只需要浏览器&#xff0c;应用程序的逻辑和数据都存储在服务端。 优点&#xff1a;维护方便缺点&#xff1a;体验一般 CS架构&#xff1a;Client/Server&#xff0c;客户端/服务器架构模式。需要单独…...

API网关Kong的鉴权与限流:高并发场景下的核心实践

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 引言 在微服务架构中&#xff0c;API网关承担着流量调度、安全防护和协议转换的核心职责。作为云原生时代的代表性网关&#xff0c;Kong凭借其插件化架构…...