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

【Rust自学】6.3. 控制流运算符-match

喜欢的话别忘了点赞、收藏加关注哦,对接下来的教程有兴趣的可以关注专栏。谢谢喵!(=・ω・=)

6.3.1. 什么是match

match允许一个值与一系列模式进行匹配,并执行匹配的模式对应的代码。模式可以是字面值、变量名、通配符等等。

match表达式想象为硬币分类机:硬币沿着带有不同大小孔的轨道滑下,每枚硬币都会从它遇到的第一个适合的孔落下。以同样的方式,值会遍历match中的每个模式,并且在第一个模式中值“适合”,该值落入要在执行期间使用的关联代码块中。

6.3.2. match的应用

来看个例子:编写一个函数,接受一枚未知的美国硬币,并以与计数机类似的方式确定它是哪种硬币并返回其价值(以美分为单位)。

enum Coin {Penny,// 1美分Nickel,// 5美分Dime,// 10美分Quarter,// 25美分
}fn value_in_cents(coin: Coin) -> u8 {match coin {Coin::Penny => 1,Coin::Nickel => 5,Coin::Dime => 10,Coin::Quarter => 25,}
}
  • match关键字后跟一个表达式,在本例中是值 coin 。这看起来与if中使用的条件表达式非常相似,但有一个很大的区别:if 的条件需要布尔值,但match可以是任何类型。本例中的coin类型是我们在第一行定义的Coin枚举。

  • 然后是花括号,花括号里有4个分支(英文叫arm),每个分支都是由待匹配的模式和它对应的代码来组成的。第一个分支Coin::Penny => 1,就使用Coin::Penny作为它的模式,中间的=>分隔模式和要运行的代码,这里要运行代码就是值:1,也就是返回1这个值。不同的分支之间使用,隔开。

  • match表达式执行时会把match后的表达式,在这里是coin,从上到下依次与里面的分支进行比较,如果模式与值匹配,则执行与该模式关联的代码。如果该模式与值不匹配,则继续执行下一个分支。匹配成功的分支所对应的代码表达式会作为整个match表达式的值进行返回。
    比如说match匹配到5美分,也就是Coin::Nickel上了,那么整个表达式的值就是5。又因为match表达式是value_in_cents这个函数中的最后一个表达式,所以它的值,也就是5,会作为函数的返回值。

  • 这里因为每个分支对应的代码都很简单,所以用=>就可以了,但如果一个分支对应的是多行代码,就需要用花括号把多行代码括起来。如下例:

fn value_in_cents(coin: Coin) -> u8 {match coin {Coin::Penny => {println!("Lucky penny!");1}Coin::Nickel => 5,Coin::Dime => 10,Coin::Quarter => 25,}
}

6.3.3. 绑定值的模式

匹配的分支可以绑定到被匹配对象的部分值,通过这个功能,就可以从枚举类型的变体中提取值。

看个例子:一位朋友正在尝试收集全部 50 个州 25 美分。当我们按硬币类型对零钱进行分类时,我们还会标出与每个25美分相关的州名称(美国州太多了,这里就只写了Alabama和Alaska这两个州)

#[derive(Debug)] // 便于打印调试 
enum UsState {  Alabama,  Alaska,  
}  enum Coin {  Penny,  Nickel,  Dime,  Quarter(UsState),  
}  fn value_in_cents(coin: Coin) -> u8 {  match coin {  Coin::Penny => {  println!("Lucky penny!");  1  },  Coin::Nickel => 5,  Coin::Dime => 10,  Coin::Quarter(state) => {  println!("State quarter from {:?}!", state);  25  }  }  
}  fn main() {  let c = Coin::Quarter(UsState::Alaska);  println!("{}", value_in_cents(c));  
}
  • 让25美分硬币(以下都叫Quarter)所对应的Coin里的变体,也就是Coin::Quarter给关联一个数据,它关联的数据就是上面的这个枚举类型UsState

  • value_in_cents函数里也需要对Quarter所在的分支稍微修改一下,匹配模式从Coin::Quarter修改到Coin::Quarter(state),意思就是把Coin::Quarter所关联的值绑定到state这个变量上,在后面的代码块里面就可以使用state这个变量,把Coin::Quarter所关联的值取出来进行使用。
    在某些情境下,Coin::Quarter所关联的值可能用不上,这时候就可以用通配符_代表不关心里面的内容:Coin::Quarter(_)

  • main函数里先声明了一个c变量,存的是Coin::Quarter(UsState::Alaska)。也就是存储了Coin::Quarter这个变体,然后其关联的值的是UsState::Alaska这个变体。最后又调用了一下value_in_cents函数。

看看输出效果:

State quarter from Alaska!
25

6.3.4. 匹配Option<T>

就以上一篇文章最后的代码例来做分析:

fn main() {  let x: i8 = 5;  let y: Option<i8> = Some(5);  let sum = match y {  Some(value) => x + value, // 如果 y 是 Some,则解包并相加  None => x,               // 如果 y 是 None,则返回 x    };  
}
  • 如果y不为None,就解包,把Some所关联的值绑定到value上,返回x + value的值
  • 如果yNone,就只返回x的值

6.3.5. match匹配必须穷举所有可能

Rust要求match覆盖到所有的可能性,这样才能保证代码的安全有效。

以上一个代码为基础稍作修改:

fn main() {  let x: i8 = 5;  let y: Option<i8> = Some(5);  let sum = match y {  Some(value) => x + value,   };  
}

输出:

error[E0004]: non-exhaustive patterns: `None` not covered--> src/main.rs:5:21|
5   |     let sum = match y {|                     ^ pattern `None` not covered|
note: `Option<i8>` defined here--> /Users/stanyin/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/option.rs:571:1|
571 | pub enum Option<T> {| ^^^^^^^^^^^^^^^^^^
...
575 |     None,|     ---- not covered= note: the matched value is of type `Option<i8>`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown|
6   ~         Some(value) => x + value,
7   ~         None => todo!(),|

Rust捕捉到了None这个可能性没有被覆盖的错误,所以报错。把处理None的分支加上就没问题了。

如果可能性太多或者不想处理其中一些可能性,这个时候就可以使用通配符_

6.3.6. 通配符

首先要把想处理的分支照常写上,其他的使用通配符_代替即可。

看例子:v是一个u8类型的变量,判断v是否是0

use rand::Rng;  // 使用外部库
fn main(){  let v: u8 = rand::thread_rng().gen_range(0..=255);  // 生成随机数println!("{}", v);  match v {  0 => println!("zero"),  _ => println!("not zero"),  }  
}

u8有256个数256种可能,使用match自然是不可能每个数都写一个分支,所以,就可以为0写一个分支,其他的使用通配符_来代替。

输出:

136
not zero
http://www.lryc.cn/news/510472.html

相关文章:

  • 大模型应用技术系列(三): 深入理解大模型应用中的Cache:GPTCache
  • 『大模型笔记』评估大型语言模型的指标:ELO评分,BLEU,困惑度和交叉熵介绍以及举例解释
  • 深度解析:Maven 和 Gradle 的使用比较及常见仓库推荐
  • SQLite本地数据库的简介和适用场景——集成SpringBoot的图文说明
  • 管理面板Ajenti的在Windows10下Ubuntu24.04/Ubuntu22.04里的安装
  • 在Python如何用Type创建类
  • Android学习19 -- NDK4--共享内存(TODO)
  • 《Cocos Creator游戏实战》非固定摇杆实现原理
  • RabbitMQ工作模式(详解 工作模式:简单队列、工作队列、公平分发以及消息应答和消息持久化)
  • 【VScode】第三方GPT编程工具-CodeMoss安装教程
  • 在JavaScript中,let 和 const有什么不同
  • Mysq学习-Mysql查询(4)
  • 安装torch-geometric库
  • Java数组深入解析:定义、操作、常见问题与高频练习
  • Docker-构建自己的Web-Linux系统-镜像webtop:ubuntu-kde
  • 【C语言练习(17)—输出杨辉三角形】
  • SpringMVC学习(二)——RESTful API、拦截器、异常处理、数据类型转换
  • React 第二十节 useRef 用途使用技巧注意事项详解
  • VIVO Java开发面试题及参考答案
  • C# Winfrom chart图 实例练习
  • iOS从Matter的设备认证证书中获取VID和PID
  • 带着国标充电器出国怎么办? 适配器模式(Adapter Pattern)
  • 破解海外业务困局:新加坡服务器托管与跨境组网策略
  • Mybatis-Plus快速入门
  • Chrome被360导航篡改了怎么改回来?
  • Coding(Jenkinsfile)+ Docker 自动化部署 Springboot —— 图文细节和一些注意事项说明
  • docker django uwsgi 报错记录
  • 数据分析思维(五):分析方法——假设检验分析方法
  • 【ES6复习笔记】集合Set(13)
  • 基础爬虫案例实战