这篇博客涉及到的知识点有 枚举的定义 、Option 枚举 、match 语法 、if let 语法 。
枚举的定义 Rust 中定义一个枚举,使用关键字 enum
,看下面的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 enum NPCType { TalkNPC, WalkNPC, BattleNPC, TaskNPC, } enum GameState { OnLogin = 1 , OnHall = 2 , OnWorld, OnBattle, OnLogOut, }
但是 Rust 的枚举是可以关联数据的,看下面的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 enum CommandType { Move(i32 , i32 , i32 ), Jump(u32 ), ChangeColor(u8 , u8 , u8 , u8 ), Smile, } fn main () { let move_command = CommandType::Move(10 , -5 , 3 ); let jump_command = CommandType::Jump(2 ); let change_color_command = CommandType::ChangeColor(110 ,128 ,55 ,255 ); let smile_command = CommandType::Smile; }
上面的代码中,可以给枚举中的字段关联数据,例如,Move 关联了3个i32类型的数据。我们可以关联任何类型的数据,也可以是自己定义的结构体,或者另一个枚举,都是可以的。
Option 枚举 Rust 没有空值(Null),但是可以使用 Option 枚举,来表示有和没有的概念。Option 枚举有两个字段,一个是 Some, 一个是 None,而 Option 是泛型的,就是说它可以面向任何类型的值 Option<T>
,用于表示任何类型的值,有值,或者没有值。Some(T) 表示有值,而 None 表示没有值,以 i32 为例子,看下面的代码
1 2 3 4 5 6 7 fn main () { let has_value: Option <i32 > = Some (200 ); let none_value: Option <i32 > = None ; println! ("has_value: {:?}" , has_value); println! ("none_value: {:?}" , none_value); }
Option 可以理解为盒子,Some(T) 表示有盒子,如果有盒子,那盒子里一定装了某种东西,也就是某种类型的值。而 None 表示没有盒子。上面的代码中,直接使用了 Some(200)
,而不是 Option::Some(200)
,是因为太常用,而被 Rust 包含在了 preload 中,所以我们可以省略前缀 Option::
。在 Rust 的学习过程中,会经常遇到 Option。特别是函数的返回值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 fn main () { let girl_age = get_girl_age(true ); println! ("girl_age: {:?}" , girl_age); let boy_age = get_girl_age(false ); println! ("boy_age: {:?}" , boy_age); } fn get_girl_age (is_girl: bool ) -> Option <u32 > { if is_girl { Some (18 ) } else { None } }
match 语法 match 语法有点类型其他语言的 switch 语法,用于条件匹配。直接看代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 enum CommandType { Move(i32 , i32 , i32 ), Jump(u32 ), ChangeColor(u8 , u8 , u8 , u8 ), Smile, } fn main () { let move_command = CommandType::Move(10 , 5 , 2 ); process_command(&move_command); let change_color_command = CommandType::ChangeColor(154 ,220 , 14 , 255 ); process_command(&change_color_command); } fn process_command (command: &CommandType) { match command { CommandType::Move(x, y, z) => { println! ("Player Move, x: {} y: {} z: {}" , x, y, z); }, CommandType::Jump(height) => { println! ("Player Jump to: {}" , height); }, CommandType::ChangeColor(r, g, b, a) => { println! ("player change color: ({}, {}, {}, {})" , r, g, b, a); }, CommandType::Smile => { println! ("player smile" ); } } }
上面的代码中,还是以 CommandType 枚举来举例。在 main 函数中定义了两个 CommandType 变量,分别使用不同的枚举,然后在 process_command 中,使用 match 语法匹配。在使用 match 匹配时, 一但类型匹配成功,就可以将其关联的值,绑定到某个变量上,然后在 match 逻辑中使用。例如上面代码中匹配上 CommandType::Move,Move 关联了三个 i32 类型的数据,所以在匹配时,就可以将关联的数据,绑定到 match 中的 x, y, z 三个变量上。
Rust 的 match 匹配必须覆盖所有的类型,如果逻辑中只关心某些类型,则可以使用 _
忽略其他类型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 enum CommandType { Move(i32 , i32 , i32 ), Jump(u32 ), ChangeColor(u8 , u8 , u8 , u8 ), Smile, } fn main () { let command = CommandType::Smile; match command { CommandType::Smile => { println! ("Smile Command" ); }, _ => { println! ("Other Command" ); } } }
if let 语法 相比于 match 匹配的繁琐,if let 语法让匹配更简洁一些
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 enum CommandType { Move(i32 , i32 , i32 ), Jump(u32 ), ChangeColor(u8 , u8 , u8 , u8 ), Smile, } fn main () { let move_command = CommandType::Move(10 , 5 , 2 ); if let CommandType::Move(x, y, z) = move_command { println! ("Player Move: x: {}, y: {}, z: {}" , x, y, z); } else { println! ("is not move command" ); } }
上面的代码中,if let 可以理解为,将右边的 move_command 和左边的枚举类型匹配,如果能匹配上,则将 move_command中的数据绑定到 x, y, z 上,然后执行匹配成功的逻辑,也就是打印出 x, y, z 的值,如果类型匹配不上,则执行匹配不上的逻辑。
为了更好的理解,下面再看一个例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 fn main () { let x = 2 ; if x == 2 { println! ("x = 2" ); } else { println! ("x != 2" ); } if let 2 = x { println! ("x = 2" ); } else { println! ("x != 2" ); } }
上面代码中 if 语句 和 if let 语句执行的打印是一样的,似乎是一个正向匹配测试,一个反向匹配测试的感觉。
Author:
iMoeGirl
Permalink:
https://imoegirl.com/2020/04/05/rust-syntax-summary-05/
License:
Copyright (c) 2019 CC-BY-NC-4.0 LICENSE
任何技术问题,欢迎在下面留言,或者直接Email我
微信公众号: 萌一小栈