rust学习十九.1、模式匹配(match patterns)
1.rust学习一、入门之搭建简单开发环境2.rust学习二、入门之运行单个脚本3.rust学习四、控制语句4.rust学习五、认识所有权5.rust学习三、基本类型6.rust学习六、简单的struct结构7.rust学习七、枚举8.rust学习八、包和模块9.rust学习九.1、集合之向量10.rust学习九.2、集合之字符串11.rust学习九.3、集合之哈希映射表12.rust学习十、异常处理(错误处理)13.rust学习十一.1、泛型(通用类型)14.rust学习十一.2、利用Trait(特质)定义通用类型的共同行为15.rust学习十一.3、生命周期标记16.rust学习十二、测试17.rust学习十二、一个I/O程序练习18.rust学习十三.1、匿名函数(闭包)19.rust学习十三.2、迭代器20.rust学习十四.1、编译和发布单元包Crate21.rust学习十四.2、工作空间(workspace)22.rust学习十五.1、智能指针基本概念23.rust学习十五.2、智能指针之Box(盒子)指针24.rust学习十五.3、智能指针相关的Deref和Drop特质25.rust学习十五.4、Rc和RefCell指针26.rust学习十五.5、引用循环和内存泄露27.rust学习十六.1、并发-乱弹和一个简单并发例子28.rust学习十六.2、并发-利用消息传递进行线程间通讯29.rust学习十六.3、并发-线程之间共享数据30.rust学习十七.1、async和await31.rust学习十八.1、RUST的面向对象(oop)和简单示例
32.rust学习十九.1、模式匹配(match patterns)
本章节大概是书本上比较特殊一个,因为它没有什么复杂的内容,通篇主要讨论模式匹配的语法。
一、两个名词
a.可反驳 - refutable
对某些可能的值进行匹配会失败的模式被称为是 可反驳的(refutable)
let Some(x) = some_option_value;如果 some_option_value 的值是 None,其不会成功匹配模式 Some(x)
b.不可反驳 -irrefutable
能匹配任何传递的可能值的模式被称为是 不可反驳的(irrefutable)。
一个例子就是 let x = 5; 语句中的 x,因为 x 可以匹配任何值所以不可能会失败
二、脑图汇总
三、示例
书本上的例子非常完善,下例的内容基本摘自书本上,少量做了一些增改。
struct Point { x: i32, y: i32, } #[allow(unused)] enum Message { Quit, Move { x: i32, y: i32 }, Write(String), ChangeColor(i32, i32, i32), } #[allow(unused)] enum Color{ Red, Green, OtherRgb(i32, i32, i32), } #[allow(unused)] enum Work{ Start, Stop, Pause(String), Cancel(Color), Finish } // 为了避免烦人的提示,直接在main函数上添加#[allow(unused)]注解,避免编译器提示未使用警告。 #[allow(unused)] fn main() { //以下例子基本从书本上复制而来 // 一、解构 ------------------------------------------------------------- //1. match 匹配字面值。 这是匹配中最简单的 let x = 1; match x { 1 => println!(" x is 壹"), 2 => println!(" x is 贰"), 3 => println!(" x is 叁"), _ => println!(" x is 其它"), } //2. match匹配命名变量。 它的主要作用是捕获变量,以便打印或者他用 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), } //3. match 匹配多个值. 多个值可以用 | 分隔 .这是属于散列值匹配 let x = 1; match x { 1 | 2 => println!("小于3的正整数"), 3 => println!("燕子三抄水"), _ => println!("不知所云...."), } //4. match 匹配区间值. 值区间使用..表示。 ..=表示区间匹配 let x = 5; match x { 1..=5 => println!("1-5之间的正整数"), _ => println!("其它"), } //5. 解构结构体 let语法. 还可以在主域中创建不在主域中定义的变量 //凭空在主域创建变量 a,b。 按照其它语言的习惯,谁看了不迷茫!!! let p = Point { x: 0, y: 7 }; let Point { x: a, y: b } = p; assert_eq!(0, a); assert_eq!(7, b); //和match枚举一样,也可以通过match捕获结构体的字段。 //在match子域内部创建变量x,y(捕获) let p = Point { x: 99, y: 7 }; match p { Point { x, y } => println!("坐标为({x},{y})"), } //6. 解构枚举,此类解构类似于match中解构结构体 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 {x} and in the y direction {y}"); } Message::Write(text) => { println!("Text message: {text}"); } Message::ChangeColor(r, g, b) => { println!("Change the color to red {r}, green {g}, and blue {b}") } } //7. 解构嵌套的结构体、枚举 -- 这个操作还是类似于利用match解构结构体 let laugh=Work::Cancel(Color::OtherRgb(100,99,98)); match laugh{ Work::Cancel(Color::OtherRgb(r,g,b))=>{ println!("r:{r},g:{g},b:{b}"); } _=>{} } //8.解构结构体和元组 - // 找不到理想的例子,用了书本上的. // 不太明白,这个算什么解构结构体和元组。 不如说解构元组吧 let ((feet, inches), Point { x, y }) = ((3, 10), Point { x: 3, y: -10 }); //来个解构元组的例子 let tup = (1, 2, 3); let (a, b, c) = tup; println!("元组tmp中的三个值分别是-a:{a},b:{b},c:{c}"); // 二.忽略 ------------------------------------------------------------------------ //9.0 使用_忽略整个值 (方法或者函数的参数) ignore_test(92,202); //10. 使用嵌套的_忽略部分值 (实际上还是忽略所有值) 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:?}"); // 10.1 这个匹配元组的稍微有点意思 // 在rust,解构数据的部分为变量的时候,就意味着隐式定义了这样的一个变量 // 例如下例中,n1,n3,n5 就是隐式定义的变量。后面的编码就尽量不要覆盖它们。 // 根据这样的趋势,是不是rust让所有类型都可以模式匹配,例如数组 let numbers = (2, 4, 8, 16, 32); match numbers { (n1, _, n3, _, n5) => { println!("Some numbers: {n1}, {n3}, {n5}") } } //10.2 数组的匹配 let foods=["水","大米","萝卜","白菜"]; match foods{ [first,_,_,third]=>{ println!("Some foods:{first},{third}"); } _=>{} } //10.3 匹配向量 -- 这个好像不行 // let books=vec!["诗经","春秋","论语"]; // match books{ // [b1,b2,b3]=>{ // println!("Some books:{b1},{b2},{b3}"); // } // } //11. 变量以下划线开头,以忽略不用警告 -- 即一个下划线开头的变量,即使你没有使用,rustc也不会警告。否则会的 // warning: unused variable: `sex` let _sex="男"; let age=99; //12. 在匹配的时候,使用..跳过不想匹配的部分 。 这个作用和下划线有点类似,不过前者针对变量个数,后者针对具体变量的值范围 match foods{ [这是地瓜,..]=>{ println!("第一格的食物是:{这是地瓜}"); } } // 三、条件 ----------------------------------------------------------------------- //13.匹配守卫 -- 类似于if的条件判断 .不如称为匹配条件 //利用匹配条件,可能会导致有些分支丢失的情况。但rustc不会报告异常,这个需要开发者自己注意。 //13.1 条件中使用当前变量 let x = Some(5); match x { Some(z) if z>10=>{ println!("Some(z) is greater than 10"); } _=>{ println!("Some(z) 小于等于 10"); } } //13.2 条件中使用其它变量 let x = 4; let y = false; match x { 4 | 5 | 6 if y => println!("yes"), 4 | 5 | 6 if !y => println!("no"), //这一句如果不写,那么这个match会有丢失的分支 _ => println!("其它情况"), } //14. @绑定, 是一个类似匹配套件的东西,只不过这个主要为枚举服务,且其表达式是比较简单,只能给一个范围? //有两种语法 val: val @ n..=m 或者 val @ n..m .自然后面一种更加友好一些 let mywork=Work::Cancel(Color::OtherRgb(100,99,98)); match mywork{ Work::Cancel(Color::OtherRgb( r @99..104,g,b))=>{ println!("r:{r},g:{g},b:{b}"); }, _=>{ println!("其它情况"); } } match mywork{ Work::Cancel(Color::OtherRgb( r @1..90,g,b))=>{ println!("r:{r},g:{g},b:{b}"); }, _=>{ println!("其它情况"); } } } fn ignore_test(_: i32, y: i32){ println!("y:{y}"); // 这个参数_无法访问。不知道rust搞这个有何意义 //println!("忽略参数:{}",_); }
结果输出不是很友好,但是也能看:
四、小结
rust的模式匹配的确是特别的体验,在以往学过的多种编程语言中,没有遇到那么多的。
固然,这在某些时候带来了不少方便,但是对于某些工程师而言并不是太友好,至少初期不是那么友好。
要说不友好,好像又不是,因为用了其中的一些匹配方式,获取对象中的值还是有点方便的。
总之,这种设计体现了rust语言的设计师的思维能力-更加灵活复杂,但又稍微显得凌乱。
在我个人的想象中,无论什么技术,最后应该都应该看起来简单优雅。
当我们学习rust的时候,这个关卡必须迈过,否则很多代码还是无法读懂的。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)