赞
踩
一个模式通常由以下组件组成
组件用于描述数据的形状,根据数据的形状进而对值进行匹配
match VALUE {
PATTERN => EXPRESSION,
PATTERN => EXPRESSION,
PATTERN => EXPRESSION,
}
match表达式必须穷尽匹配值的所有可能性
可以混合使用 if let、else if 和 else 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 is_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"); } }
反复执行同一个模式匹配直到匹配失败,自动退出循环
let mut stack = Vec::new();
stack.push(1);
stack.push(2);
stack.push(3);
while let Some(top) = stack.pop() {
println!("{}", top);
}
for 模式 in 值(通常是一个迭代器的返回值)
例:迭代适配器enumerate
会生成一个包含索引和值本身的元组
let v = vec!['a', 'b', 'c'];
for (index, value) in v.iter().enumerate() {
println!("{} is at index {}", value, index);
}
实际上,所有的let语句都是模式匹配
let 模式 = 表达式;
比如之前我们使用过的解构元组
let (x,y,z) = (1,2,3);
传参过程是模式匹配(因为传参过程类似于一个赋值过程嘛)
比如通过模式匹配解构元组实参:
fn print_coordinates(&(x, y): &(i32, i32)) {
println!("Current location: ({}, {})", x, y);
}
fn main() {
let point = (3, 5);
print_coordinates(&point);
}
匹配时要求的是“全等”
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);
}
在模式中使用|
来表示“或”
let x = 1;
match x {
1 | 2 => println!("one or two"),
3 => println!("three"),
_ => println!("anything"),
}
使用a..=b
表示匹配一个a到b的闭区间,比如1..=4
就等同于1|2|3|4
范围模式只被允许使用数值或者char值
使用语法
结构体名 {
字段1名:模式1,
字段2名:模式2,
} = 结构体实例
来直接获得结构体内部的值
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);
}
fn main() {
let p = Point { x: 0, y: 7 };
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 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 ) } } }
模式可以嵌套使用,只要能表达清楚数据的结构就好
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::ChangeColor(Color::Rgb(r, g, b)) => { println!( "Change the color to red {}, green {}, and blue {}", r, g, b ) } Message::ChangeColor(Color::Hsv(h, s, v)) => { println!( "Change the color to hue {}, saturation {}, and value {}", h, s, v ) } _ => () } }
let ((feet,inches),Point {x,y}) = ((3,10),Point {x:-1,y:10});
_
忽略整个值比如为结构体实现trait时,trait的方法包含了不需要的参数,就用得上忽略模式了
fn foo(_: i32, y: i32) {
println!("This code only uses the y parameter: {}", y);
}
fn main() {
foo(3, 4);
}
_
忽略值的某些部分把被忽略的部分用_
补上就好
fn main() {
let numbers = (2, 4, 8, 16, 32);
match numbers {
(first, _, third, _, fifth) => {
println!("Some numbers: {}, {}, {}", first, third, fifth)
},
}
_
开头的名称来忽略未使用的变量如果一个变量定义了却未被使用,会触发警告
使用_
开头则可以忽略未使用的变量
_
的区别:_
不会执行变量绑定,而_变量名
则会执行变量绑定let s = Some(String::from("Hello!"));
if let Some(_s) = s {
println!("found a string");
}
//报错!
//println!("{:?}", s);
let s = Some(String::from("Hello!"));
if let Some(_) = s {
println!("found a string");
}
println!("{:?}", s);
..
忽略值的剩余部分..
模式可以忽略一个值中没有被我们显式匹配的部分
..
会自动展开并填充任意多个值
let numbers = (2, 4, 8, 16, 32);
match numbers {
(first, .., last) => {
println!("Some numbers: {}, {}", first, last);
},
}
使用时不能出现歧义,比如下面这个例子就是有歧义
let numbers = (2, 4, 8, 16, 32);
match numbers {
(.., second, ..) => {
匹配守卫(match guard)是一个指定于 match 分支模式之后的额外 if 条件,它也必须被满足才能选择此分支。
let num = Some(4);
match num {
Some(x) if x < 5 => println!("less than five: {}", x),
Some(x) => println!("{}", x),
None => (),
}
@
绑定运算符(@)允许我们在创建一个存放值的变量的同时测试其值是否匹配模式
enum Message { Hello { id: i32 }, } 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) }, }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。