当前位置:网站首页>Rust 中的枚举和控制流运算
Rust 中的枚举和控制流运算
2022-06-27 17:58:00 【用户3147702】
1. 引言
枚举类型对于 Java 程序员来说不会陌生,它是列举常量成员的非常好用的工具。在 rust 中也同样如此,并且在 rust 中,枚举类型比其他语言中更为常用,尤其是 Option、Result 等语言自身定义的枚举类型,为 rust 本身添加了非常强大而独特的语法特性。
2. 枚举类型
与 java 语言枚举中关注枚举的类型和值不同,rust 中的枚举专注于类型,枚举成员本身是不对应具体的值的。
2.1 枚举类型的定义
例如,下面的枚举类型定义了 IPv4 和 IPv6 两个成员:
enum IpAddrKind {
V4,
V6,
}
fn main() {
let four = IpAddrKind::V4;
let six = IpAddrKind::V6;
route(IpAddrKind::V4);
route(IpAddrKind::V6);
}
fn route(ip_kind: IpAddrKind) {}2.2 枚举类型的数据
上面的例子中,定义了一个枚举类型,并且创建了相应类型的的变量。
但我们往往不仅希望变量体现出具体的类型,还希望变量具备具体的值。
此时我们可以将枚举类型与具体的值再进行一层封装,从而得到一个同时包含类型和值的结构体。
fn main() {
enum IpAddrKind {
V4,
V6,
}
struct IpAddr {
kind: IpAddrKind,
address: String,
}
let home = IpAddr {
kind: IpAddrKind::V4,
address: String::from("127.0.0.1"),
};
let loopback = IpAddr {
kind: IpAddrKind::V6,
address: String::from("::1"),
};
}进一步,我们可以通过 rust 的语法糖来简化上述结构体的定义:
fn main() {
enum IpAddr {
V4(String),
V6(String),
}
let home = IpAddr::V4(String::from("127.0.0.1"));
let loopback = IpAddr::V6(String::from("::1"));
}这样一来,数据被直接附加在了枚举类型上。相较于上面通过结构体定义的复合类型,枚举类型上直接附加数据还可以定义不同类型的数据:
fn main() {
enum IpAddr {
V4(u8, u8, u8, u8),
V6(String),
}
let home = IpAddr::V4(127, 0, 0, 1);
let loopback = IpAddr::V6(String::from("::1"));
}3. 特殊的枚举类型 Option
Option 是 rust 标准库定义的一个枚举。Option 的存在,尝试去解决令无数软件开发工程师抓狂的空指针、空引用问题。
3.1 Option 的定义
Option 的定义如下:
enum Option<T> {
None,
Some(T),
}看起来非常简单,如果一个函数或是表达式要返回一个 T 类型的数据,并且 T 类型的数据有可能为空。那么用 Option 封装将会是一个更好的选择。因为 T 类型的数据如果为空值,而使用者忽略了这一情况,将会产生程序的 panic,这通常是我们不希望看到的。
3.2 Option 变量的创建
可以这样获得一个 Option 的数据:
let x: Option<u32> = Some(2);
assert_eq!(x.is_some(), true);
let x: Option<u32> = None;
assert_eq!(x.is_some(), false);
let x: Option<u32> = None;
assert_eq!(x.is_none(), true);一旦一个返回值被 Option 封装起来,使用者就必须处理值为 None 的情况,这一显式的处理,避免了意外的空引用、空指针的产生。
3.3 Option 数据的获取
要想获取 Option 中的实际数据,可以通过很多种方法,此处介绍 unwrap 方法。
1. unwrap 方法
unwarp 方法需要保证有值,一旦值为 None,那么就会让程序 panic。
// 如果值为 None,则 unwrap 将导致 panic
let x = Some("air");
assert_eq!(x.unwrap(), "air");2. unwrap_or 方法
与 unwrap 方法不同,unwrap_or 方法允许传递一个参数,当值为 None 时,则以这个参数作为返回值。
assert_eq!(Some("car").unwrap_or("bike"), "car");
assert_eq!(None.unwrap_or("bike"), "bike");3. unwrap_or_else 方法
unwrap_or 方法让我们能够提供默认的返回值,但更为高级的是 unwrap_or_else 方法,它允许我们创建一个函数或表达式来决定当值为 None 时返回什么。
let vec = vec![1,2,3];
let a: &i32 = vec.get(4).unwrap_or_else(||{
vec.get(0)
});4. 控制流 match
正如在 java 语言中,枚举类型搭配 switch-case 可以让代码显得十分简洁易于维护。在 Rust 中,通过强大的控制流运算符 match 搭配枚举也同样可以实现类似的效果。
4.1 match 的使用
下面就是一个 match 控制流的示例:
fn value_in_cents(coin: Coin) -> u8 {
match coin {
Coin::Penny => {
println!("Lucky penny!");
1
}
Coin::Nickel => 5,
Coin::Dime => 10,
Coin::Quarter => 25,
}
}4.2 match 获取枚举值
对于某个枚举拥有他的枚举数据值时,也可以进行 match:
fn value_in_cents(coin: Coin) -> u8 {
match coin {
Coin::Penny => 1,
Coin::Nickel => 5,
Coin::Dime => 10,
Coin::Quarter(state) => {
println!("State quarter from {:?}!", state);
25
}
}
}4.3 Option 与 match 匹配
有了上述 4.2 节的示例,我们就可以来处理 Option 类型的数据了:
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);这个示例定义了一个函数,它获取一个 Option<i32> ,如果其中含有一个值,将其加一。如果其中没有值,函数应该返回 None 值,而不尝试执行任何操作。
4.4 通配模式
需要注意的是,如果要使用 match 控制流,枚举类型包含的每一个类型都必须要出现在 match 块中。
但有时,我们希望有一种模式可以用来代替所有其他情况,类似于其他语言 switch 语句中的 default 关键字,在 Rust 中,同样是支持这一特性的,那就是 _ 占位符:
let dice_roll = 9;
match dice_roll {
3 => add_fancy_hat(),
7 => remove_fancy_hat(),
_ => (),
}
fn add_fancy_hat() {}
fn remove_fancy_hat() {}5. if let 控制流
很多时候,我们只想简洁地获取一个枚举对应的值或表达式,通过 match 表达式往往会显得太过复杂。此时,if let 可能会是更好的选择,例如:
#[derive(Debug)]
enum UsState {
Alabama,
Alaska,
// --snip--
}
enum Coin {
Penny,
Nickel,
Dime,
Quarter(UsState),
}
fn main() {
let coin = Coin::Penny;
let mut count = 0;
if let Coin::Quarter(state) = coin {
println!("State quarter from {:?}!", state);
} else {
count += 1;
}
}边栏推荐
- Gartner聚焦中国低代码发展 UniPro如何践行“差异化”
- Vs code runs "yarn run dev" and reports "yarn": the file XXX cannot be loaded
- 网络传输是怎么工作的 -- 详解 OSI 模型
- 带你认识图数据库性能和场景测试利器LDBC SNB
- New Zhongda chongci scientific and Technological Innovation Board: annual revenue of 284million and proposed fund-raising of 557million
- 多伦多大学博士论文 | 深度学习中的训练效率和鲁棒性
- 在线文本按行批量反转工具
- 惊呆!原来 markdown 的画图功能如此强大!
- Crawl national laws and Regulations Database
- shell脚本常用命令(四)
猜你喜欢

External interrupt experiment based on stm32f103zet6 library function

UE4实现长按功能

Function key input experiment based on stm32f103zet6 Library

华大单片机KEIL添加ST-LINK解决方法

GIS remote sensing R language learning see here

爬取国家法律法规数据库

基于STM32F103ZET6库函数按键输入实验

308. 二维区域和检索 - 可变 线段树/哈希

国际数字经济学院、华南理工 | Unified BERT for Few-shot Natural Language Understanding(用于小样本自然语言理解的统一BERT)

指针和结构体
随机推荐
多伦多大学博士论文 | 深度学习中的训练效率和鲁棒性
ABAP随笔-EXCEL-3-批量导入(突破标准函数的9999行)
券商经理的开户二维码开户买股票安全吗?有谁知道啊
基于STM32F103ZET6库函数外部中断实验
过关斩将,擒“指针”(下)
redis集群系列三
Redis 原理 - String
可靠的分布式锁 RedLock 与 redisson 的实现
OpenSSL client programming: SSL session failure caused by an obscure function
Substrate及波卡一周技术更新速递 20220425 - 20220501
Bit. Store: long bear market, stable stacking products may become the main theme
Making single test so simple -- initial experience of Spock framework
Bit.Store:熊市漫漫,稳定Staking产品或成主旋律
UE4实现长按功能
Bit.Store:熊市漫漫,稳定Staking产品或成主旋律
NVIDIA Clara-AGX-Developer-Kit installation
ABAP-CL_OBJECT_COLLECTION工具类
工作流自动化 低代码是关键
OpenSSL client programming: SSL session failure caused by an obscure function
在线文本按行批量反转工具