一、let模式匹配
在其它一些語言中,let x = 5 之類的語句,僅僅只是賦值語句。但是在rust中,可以換個角度理解,認為5這個值匹配到了x變量。如果覺得有些牽強,可以再來一個示例:
let (a,b)=(1,3); println!("{},{}",a,b);
上面的示例,表示(1,3)這個元組,匹配(a,b)這一組變量,即a=1, b=3,類似的,struct也可以這樣匹配:
struct Point { x: i32, y: i32, } fn main() { let p = Point { x: 10, y: 20 }; //模式匹配 let Point { x, y } = p; //x=10,y=20 println!("x:{},y:{}", x, y); }
二、match匹配
2.1 匹配簡單類型
let x = 1; match x { 1 => println!("x=1"), 2 => println!("x=2"), //"_"相當於java中switch的default _ => println!("default"), } let y = 2; match y { //匹配1或2 1 | 2 => println!("y=1 or 2"), _ => println!("default"), } let z = 1; match z { //匹配1到5 1..=5 => println!("z between 1 and 5"), _ => println!("default"), } let c = 'z'; match c { //匹配a到z 'a'..='z' => println!("{} in [a-z]", c), _ => println!("other"), }
2.2 匹配枚舉
以最常用的Option enum為例:
let x = Some(2); let x_result = match x { //精確匹配Some(5),x=Some(2),會匹配失敗 Some(5) => 5, _ => -1, }; println!("{}",x_result); let x = Some(2); let x_result = match x { //只要x有值,就能匹配成功 Some(n) => n, _ => -1, }; println!("{}",x_result); let x = Some(3); let x_result = match x { //匹配時,還能指定條件,3>1,下面這行會匹配成功 Some(n) if n>1 => n, _ => -1, }; println!("{}",x_result);
輸出:
-1
2
3
另外,有些情況下,match還可以用if let語法糖簡化代碼:
if let Some(v) = Some(5) { println!("{}", v); }; //上面的代碼,等效於下面這幾行: let w = Some(5); match w { Some(n) => { println!("{}", n) } _ => {} }
有時候,只需要匹配enum類型,不關注值,可以用_來忽略值
let x = Some(4); let y = Some(5); match(x,y){ (Some(_),Some(_)) => println!("both are Some Type"), _ => println!("others") }
關於“_”,還有一些小技巧,如果只聲明1個變量,不使用,rust編譯器會警告:
上圖的提示,已經給出建議,可以加_,即改成let _x=10,就不會報警了。
另外_在模式匹配中,還可以避免所有權轉移:
let s = Some(String::from("hello")); //由於_不關注值,所以s的所有權不會move到_ if let Some(_) = s{ println!("found a string"); } //這里能正常輸出 println!("s:{:?}",s);
但如果,把Some(_),換成其它方式,比如
不僅僅是系統自帶的enum,開發人員自定義的enum也一樣可以進行匹配:
enum Order { New { order_id: i32 }, } let o1 = Order::New { order_id: 1 }; match o1 { Order::New { order_id: x } if x >= 0 && x <= 10 => { println!("order_id:{} between 0 and 10", x) } _ => {} } //與上面的寫法等效(注意多了1個@符號,表示把匹配到的值,賦值到@修飾的變量n里) match o1 { Order::New { order_id: n @ 1..=10, } => println!("order_id:{} between 0 and 10", n), _ => {} }
2.3 匹配元組
let t = (1, 2,3); match t { //僅匹配第1項,其它元素忽略 (1, ..) => println!("first item is 1"), _ => println!("default"), } let t = (2, 3); match t { //匹配第1項,第2項放到變量n里 (1, n) => println!("{},{}", 1, n), _ => println!("default"), } let t = (1, 2, 3, 4, 5, 6); match t { //匹配第1項與最后1項 (1, .., 6) => println!("first:1,last:6"), _ => println!("others"), }
2.4 匹配struct
struct Point { x: i32, y: i32, } let p = Point { x: 10, y: 20 }; match p { Point { x: 10, y: 20 } => println!("完全匹配!"), Point { x: 5, y } => println!("要求x匹配5,y無所謂"), Point { x, y } => println!("p中的x,y匹配到{},{}", x, y), _ => println!("others"), }