枚举与匹配模式
土豆 2023/3/11
# 枚举
定义枚举
enum IpAddrKind {
V4,
V6,
}
枚举值
let four = IpAddrKind::V4;
let six = IpAddrKind::V6;
使⽤结构体来存储 IP 地址的数据和 IpAddrKind 变体
enum IpAddrKind {
V4,
V6,
}
struct IpAddr {
kind: IpAddrKind,
address: String,
}
fn main() {
let four = IpAddrKind::V4;
let six = IpAddrKind::V6;
let home = IpAddr {
kind: IpAddrKind::V4,
address: String::from("127.0.0.1"),
};
let loopback = IpAddr {
kind: IpAddrKind::V6,
address: String::from("::1"),
};
}
枚举嵌入各种数据
Quit 没有任何关联数据
Move 包含了⼀个匿名结构体
Write 包含了⼀个 String。
ChangeColor 包含了 3 个 i32 值。
enum Message {
Quit,
Move {x:i32,y:i32},
Write(String),
ChangeColor(i32,i32,i32)
}
// 相同结构
struct QuitMessage; // 空结构体
struct MoveMessage {
x: i32,
y: i32,
}
struct WriteMessage(String); // 元组结构体
struct ChangeColorMessage(i32, i32, i32); // 元组结构体
定义枚举方法
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(i32, i32, i32),
}
impl Message {
fn call(&self) {
// 方法体
}
}
fn main() {
let m = Message::Write(String::from("hello"));
m.call();
}
# 控制流运算符 match
常强⼤的控制流运算符:match,它允许将⼀个值与⼀系列的模式相⽐较,并根据匹配的模式执⾏相应代码。
#[derive(Debug)]
enum Coin {
Penny,
Nickel,
Dime,
Quarter,
}
fn value_in_cents(coin: Coin) -> u32 {
match coin {
Coin::Penny => 1,
Coin::Nickel => 5,
Coin::Dime => 10,
Coin::Quarter => 25,
}
}
fn main() {
let penny = Coin::Penny;
// Coin::Penny 被匹配成功,返回1
print!("coin{}\n", value_in_cents(penny)); // coin1
}
绑定值的模式(匹配括号中的值)
#[derive(Debug)]
enum UsState {
Alabama,
Alaska,
}
enum Coin {
Penny,
Nickel,
Dime,
Quarter(UsState), // Quarter 变体存放了一个UsSate值
}
fn value_in_cents(coin: Coin) -> u32 {
match coin {
Coin::Penny => 1,
Coin::Nickel => 5,
Coin::Dime => 10,
Coin::Quarter(state) => {
// 打印state的值
println!("State quarter from {:?}!", state);
25
}
}
}
fn main() {
let quarter = Coin::Quarter(UsState::Alabama);
println!("coin{}", value_in_cents(quarter))
}
// 输出
// State quarter from Alabama!
// coin25
匹配 Option<T>
想要编写⼀个接收 Option
fn plus_one(x: Option<i32>) -> Option<i32> {
match x {
None => None,
Some(i) => Some(i + 1),
}
}
fn main() {
let five = Some(5);
let six = plus_one(five);
let none = plus_one(None);
println!("six:{:?}", six); // six:Some(6)
println!("none:{:?}", none) // none:None
}
匹配必须穷举所有的可能
fn plus_one(x: Option<i32>) -> Option<i32> {
match x {
Some(i) => Some(i + 1),
}
}
因为没有穷举所有的可能性编译报错,Rust 知道我们没有覆盖所有可能的情形,甚⾄能够确切地指出究竟是哪些模式被我们漏掉了!Rust 中的匹配是穷尽的(exhausitive):我们必须穷尽所有的可能性,来确保代码是合法有效的。特别是在这个 Option
error[E0004]: non-exhaustive patterns: `None` not covered
--> main.rs:4:11
|
4 | match x {
| ^ pattern `None` not covered
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error: aborting due to previous error
For more information about this error, try `rustc --explain E0004`.
_通配符
不想匹配所有情况
let some_u8_value = 0u8;
match some_u8_value {
1 => println!("one"),
3 => println!("three"),
_ => (), // 匹配剩余的其他值,没必要列出0~255的所有值
}
简单控制流 if let
示例一
fn main() {
let some_u8_value = Some(3);
// 示例一等于3时执行
match some_u8_value {
Some(3) => println!("three"),
_ => (),
}
// if let实现
if let Some(3) = some_u8_value {
println!("three");
}
}
示例二(match 方式)
#[derive(Debug)]
enum UsState {
Alabama,
Alaska,
}
enum Coin {
Penny,
Nickel,
Dime,
Quarter(UsState), // Quarter 变体存放了一个UsSate值
}
fn main() {
// 示例二 如果是Quarter就打印,否则count 加一
let mut count = 0;
let coin = Coin::Penny;
match coin {
Coin::Quarter(state) => println!("state quarter from {:?}!", state),
_ => count += 1,
}
println!("count:{}", count); // count:1
}
示例二(if else)
#[derive(Debug)]
enum UsState {
Alabama,
Alaska,
}
enum Coin {
Penny,
Nickel,
Dime,
Quarter(UsState), // Quarter 变体存放了一个UsSate值
}
fn main() {
// 示例二 如果是Quarter就打印,否则count 加一
let mut count = 0;
let coin = Coin::Penny;
if let Coin::Quarter(state) = coin {
println!("state quarter from {:?}!", state)
} else {
count += 1;
}
println!("count:{}", count); // count:1
}