掌握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 语言的模式匹配功能强大,不仅能处理简单的值匹配,还能解构和操作复杂的数据结构。通过深入学习模式匹配,程序员可以更加高效地编写出清晰、简洁且易于维护的代码。 Rus…...
HFSS 3D Layout中Design setting各个选项的解释
从HFSS 3D LAYOUT菜单中,选择Design Settings打开窗口,会有六个选项:DC Extrapolation, Nexxim Options, Export S Parameters, Lossy Dielectrics, HFSS Meshing Method, and HFSS Adaptive Mesh. DC Extrapolation 直流外推 直流外推分为标…...
线性表之链表详解
欢迎来到我的:世界 希望作者的文章对你有所帮助,有不足的地方还请指正,大家一起学习交流 ! 目录 前言线性表的概述链表的概述 内容链表的结构链表节点的定义 链表的基本功能单向链表的初始化链表的插入操作头插操作尾插操作 链表的删除操作头…...
C/C++使用AddressSanitizer检测内存错误
AddressSanitizer 是一种内存错误检测工具,编译时添加 -fsanitizeaddress 选项可以在运行时检测出非法内存访问,当发生段错误时,AddressSanitizer 会输出详细的错误报告,包括出错位置的代码行号和调用栈,有助于快速定位…...
【EI和Scopus检索】国际人工智能创新研讨会(IS-AII 2025)
国际人工智能创新研讨会(IS-AII 2025)将于2025年1月11日-1月14日在贵阳盛大举行。会议将聚焦计算机科学、人工智能、机器人科学与工程等相关研究领域,广泛邀请国内外知名专家学者,共同探讨相关学科领域的最新发展方向及行业前沿动…...
在OceanBase 中,实现自增列的4种方法
本文作者:杨敬博,爱可生 DBA 团队成员。 背景描述 在OceanBase数据库中,存在MySQL租户与Oracle租户两种模式,本文主要讲解在 OceanBase 的Oracle模式(以下简称OB Oracle),创建自增列的4种方式&…...
LWE算法分类及基本加解密算法示例
LWE(Learning With Errors)算法是一种基于格(lattice)的密码学原语,广泛应用于构建抗量子计算的加密方案。LWE算法的安全性基于最坏情况下的格问题(如最短向量问题SVP和最近向量问题CVP)&#x…...
【论文阅读】Learning dynamic alignment via meta-filter for few-shot learning
通过元滤波器学习动态对齐以实现小样本学习 引用: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 协议?SPP 的适用场景 二、SPP的工作流程1. 蓝牙设备初始化2. 设备发现与配对3. 建立 SPP 连接4. 数据传输5. 关闭连接 三、进阶应用与常见问题蓝牙连接中断与重试机制数据传输中的延迟与错误处理电池消耗和蓝牙优化 总结 前言 蓝…...
系统学习领域驱动设计-感悟-高尚名词篇
高尚名词 高尚名词通俗意思知识消化开发代码过程中的业务理解持续学习团队角度,持续沉淀文档沉淀业务理解,教会更多的新人,不让某些员工掌握知识壁垒...
人工智能(AI)和机器学习(ML)技术学习流程
目录 人工智能(AI)和机器学习(ML)技术 自然语言处理(NLP): Word2Vec: Seq2Seq(Sequence-to-Sequence): Transformer: 范式、架构和自注意力: 多头注意力: 预训练、微调、提示工程和模型压缩: 上下文学习、思维链、全量微调、量化、剪枝: 思维树、思维…...
<Project-20 YT-DLP> 给视频网站下载工具 yt-dlp/yt-dlp 加个页面 python web
介绍 yt-dlp Github 项目:https://github.com/yt-dlp/yt-dlp A feature-rich command-line audio/video downloader 一个功能丰富的视频与音频命令行下载器 原因与功能 之前我用的 cobalt 因为它不再提供Client Web功能,只能去它的官网使用。 翻 redd…...
【Android】Gradle 7.0+ 渠道打包配置
声明 该配置主要解决打包apk/aab需要动态修改渠道字段,方便区分渠道上架国内商店。 暂不支持批量打包(7.4版本无法通过只修改outputFileName的形式批量处理) 因为构建时需要拷贝/创建Output,然后修改outputFileName才能处理批量打包,但拷贝/创建在高版本中失效了。 目前的…...
Web应用性能测试工具 - httpstat
在数字化时代,网站的性能直接影响用户体验和业务成功。你是否曾经在浏览网页时,遇到加载缓慢的困扰?在这个快速变化的互联网环境中,如何快速诊断和优化Web应用的性能呢?今天,我们将探讨一个强大的工具——h…...
MySQL 【流程控制】函数
目录 1、CASE 语句用于流程控制中的多分支情况。 2、IF() 函数根据测试条件是否为真分别返回指定的值。 3、IFNULL() 函数,如果第一个参数为 NULL,返回第二个参数,否则返回第一个参数。 4、NULLIF() 函数根据两个参数是否相等决定返回 NUL…...
python 天气数据可视化
Python爬取天气数据及可视化分析 https://blog.csdn.net/weixin_69423932/article/details/135184643...
【HarmonyOS Next】数据本地存储:@ohos.data.preferences
【HarmonyOS Next】数据本地存储:ohos.data.preferences 在开发现代应用程序时,数据存储是一个至关重要的过程。应用程序为了保持某些用户设置、应用状态以及其他小量数据信息通常需要一个可靠的本地存储解决方案。在 HarmonyOS Next 环境下,…...
使用BaGet快速搭建nuget服务
BaGet是基于 asp.net core编写的一个轻量级的 nuget管理服务,安装部署非常简单。 * Nuget版本号规范: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搭建 四、软件搭建五、测试结果六、总结 前言 随着嵌入式系统和物联网设备的快速发展,高效可靠的存储解决方案变得越来越重要。雷龙发展推出的SD NA…...
【功能介绍】信创终端系统上各WPS版本的授权差异
原文链接:【功能介绍】信创终端系统上各WPS版本的授权差异 Hello,大家好啊!今天给大家带来一篇关于信创终端操作系统上WPS Office各版本(不包括政务版、企业版等)之间的差异的文章。WPS Office作为国内广泛使用的办公软…...
爱诗科技发布PixVerse R1,革新AI视频创作
4月2日,爱诗科技在闪电发布周推出全球首个通用实时世界模型——PixVerse R1,标志AI视频创作转向实时交互。上线后吸引众多创作者,还带来两项功能升级。模型发布意义重大爱诗科技此次推出的PixVerse R1,让AI视频创作从传统“一次性…...
利用快马平台快速构建node.js express api原型,十分钟搭建可运行后端服务
今天想和大家分享一个快速搭建Node.js后端服务的实践心得。作为一个经常需要验证想法的开发者,我发现用InsCode(快马)平台可以省去很多环境配置的麻烦,特别适合做原型开发。 为什么选择Node.jsExpress组合 Express框架是Node.js生态中最轻量灵活的Web框架…...
Token火了,一文读懂词元经济产业链
“词元(Token)是新的大宗商品。”在英伟达2026年度开发者大会(GTC)上,英伟达创始人兼CEO黄仁勋首次提出词元经济。 黄仁勋提出一个公式:收入每瓦词元数可用千兆瓦数。他解释称,数据中心如今已经…...
保姆级教程:在ROS Noetic下用DWA算法让无人机在已知地图里自动巡航(附完整配置文件)
无人机自主导航实战:ROS Noetic中DWA算法的深度配置与避坑指南 当你在Gazebo仿真环境中看着无人机缓缓升起,准备开始它的首次自主飞行时,那种期待与忐忑交织的感觉,想必每个ROS开发者都深有体会。本文将从实战角度出发,…...
量子系统的 纯态 和 混合态 的 状态向量 和 密度矩阵
首先,纯态完全可以描述多个纠缠态(例如一个Bell态)的叠加,而且这是多体量子系统中纯态最核心、最非经典的应用。即,量子系统具有精确已知的任何某个具体状态 ,称为处于纯态,这时 且 ÿ…...
ChatGPT_JCM前端构建工具对比:Webpack、Vite与Rollup
ChatGPT_JCM前端构建工具对比:Webpack、Vite与Rollup 【免费下载链接】ChatGPT_JCM 项目地址: https://gitcode.com/gh_mirrors/ch/ChatGPT_JCM ChatGPT_JCM是一个基于AI技术的前端项目,在开发过程中选择合适的构建工具对于提升开发效率和优化项…...
《Linux网络编程》2.Socket编程(UDP/TCP)
💡Yupureki:个人主页 ✨个人专栏:《C》 《算法》《Linux系统编程》《高并发内存池》《MySQL数据库》 《个人在线OJ平台》《Linux网络编程》 🌸Yupureki🌸的简介: 目录 1. UDP编程 1.1 常用接口 1.1.1 socket() – 创建套接字 1.1.2 bin…...
为什么传统绩效考核正在被OKR取代?2026年企业目标管理的智能化选择
OKR绩效管理系统是帮助企业实施目标与关键成果法(Objectives and Key Results)的数字化工具,通过可视化目标设定、进度追踪和结果评估,让团队目标对齐更清晰、执行更高效。2026年的主流系统已集成AI能力,能自动生成目标…...
效率革命:基于快马AI生成opencode自动化安装工具,告别手动敲命令
效率革命:基于快马AI生成opencode自动化安装工具,告别手动敲命令 最近在团队协作中,经常遇到新成员需要配置opencode开发环境的情况。每次看到同事手动输入一长串命令,还要处理各种依赖报错,我就想:能不能…...
项目介绍 MATLAB实现基于栅格地图法(Grid Map)进行无人机三维路径规划的详细项目实例(含模型描述及部分示例代码) 专栏近期有大量优惠 还请多多点一下关注 加油 谢谢 你的鼓励是我前行的动力
MATLAB实现基于栅格地图法(Grid Map)进行无人机三维路径规划的详细项目实例 更多详细内容可直接联系博主本人 或者访问对应标题的完整博客或者文档下载页面(含完整的程序,GUI设计和代码详解) 随着无人机技术的迅速…...
