6.1 枚举
枚举允许我们列举所有可能的值来定义一个类型
1 2 3 4
| enum IpAddsKind { V4, V6, }
|
- 其中
V4
,V6
称为该枚举类型的变体
- 枚举的变体都位于对应的命名空间下,用
::
进行分隔
1
| let four = IpAddsKind::V4;
|
该类型也可以作为函数参数,例如
1
| fn route(ip_kind: IpAddsKind) {}
|
枚举类型也可以作为struct的字段类型,例如
1 2 3 4
| struct IpAddr { kind: IpAddsKind, address: String, }
|
任意类型的数据也可以在枚举的变体之中,例如
1 2 3 4 5 6 7 8 9
| enum IpAddsKind { V4(u8, u8, u8, u8), V6(String), }
fn main() { let home = IpAddsKind::V4(127, 0, 0, 1); let loopback = IpAddsKind::V6(String::from("::1")); }
|
- 这里我们在
V4
嵌入了4个u8
,V6
嵌入了String
- 事实上,任意数据都可以嵌入,比如
struct
和另外一种enum
为枚举定义方法
和struct
一样,我们可以用impl
为枚举类型定义方法,例如
1 2 3 4 5 6 7 8 9 10 11 12 13
| enum IpAddsKind { V4(u8, u8, u8, u8), V6(String), }
impl IpAddsKind { fn call(&self) {} }
fn main() { let home = IpAddsKind::V4(127, 0, 0, 1); home.call(); }
|
6.2 Option枚举
Option枚举是定义在标准库里的基本方法,属于预导入模块(prelude)
- 用于描述某个值可能存在(某个类型)或不存在的情况
- 因为是prelude中的模块,是因不需要使用
Option::
在C/C++和Python中,都有NULL
/ nullptr
或者None
这种表示空的值,但这可能会导致一些问题,因此Rust舍弃了定义空
取而代之,为了描述那些因为某种原因缺失而无效的值,Rust定义了实现该功能的概念,即枚举类型Option<T>
在标准库中,其被定义为
1 2 3 4
| enum Option<T> { Some(T), None, }
|
例如
1 2 3
| let some_number = Some(5); let some_string = Some("a string"); let absent_number: Option<i32> = None;
|
- 其中前2个编译器可以自动推断,最后一个需要指定类型
Option<T>
比Null
的优势
在Rust中,Option<T>
和T
是不同的类型,例如
1 2 3
| let x: i8 = 5; let y: Option<i8> = Some(5); let sum = x + y;
|
在Rust中,只要这个值不是Option<T>
,作为T
就可以放心进行操作
如果需要取得Option<T>
中的值,可以做类型转换
6.3 Match: 控制流运算符
Rust中的match是一个强大的控制流运算符,允许一个值和一系列模式进行匹配,并执行对应的匹配代码
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| enum Coin { Penny, Nickel, Dime, Quarter, }
fn value_in_cents(coin: Coin) -> u8 { match coin { Coin::Penny => { println!("Lucky penny!"); 1 }, Coin::Nickel => 5, Coin::Dime => 10, Coin::Quarter => 25, } }
|
绑定值的模式匹配
匹配的分支可以被绑定到匹配对象的部分值
示例
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 32
| #[derive(Debug)] enum UsState { Alabama, Alaska, }
enum Coin { Penny, Nickel, Dime, Quarter(UsState), }
fn value_in_cents(coin: Coin) -> u8 { match coin { Coin::Penny => { println!("Lucky penny!"); 1 }, Coin::Nickel => 5, Coin::Dime => 10, Coin::Quarter(state) => { println!("State quarter from {:?}!", state); 25 }, } }
fn main() { let c = Coin::Quarter(UsState::Alabama); value_in_cents(c); }
|
匹配Option<T>
示例
1 2 3 4 5 6 7 8 9 10 11 12
| 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); }
|
Match匹配默认必须枚举所有的可能情况
如果只希望枚举部分,对于剩余部分可以用通配符_
来指代,且放在最后一个模式中,例如
1 2 3 4 5 6 7 8 9 10
| fn main() { let x: i8 = 5; match x { 1 => println!("one"), 2 => println!("two"), 3 => println!("three"), 4 => println!("four"), _ => () } }
|
- 这里的
i8
有256中可能的整数,因此如果不加_
的话,我们需要枚举256种情况
6.4 简单控制流if let
该控制流处理的是指考虑单一匹配的情况,是match的一种语法糖
1 2 3 4 5 6 7 8 9 10 11
| fn main() { let x: i8 = 3; match x { 1 => println!("one"), _ => () }
if let 1 = x { println!("one"); } }
|
- 这里的
if let
的效果和match
的效果一样
- 注意这里的
1 = x
的单个模式的匹配,不能写成x = 1
或1 == x
等
此外,if let
还可以搭配else
使用,来执行match
中_ =>
的部分,例如
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| fn main() { let x: i8 = 1; match x { 1 => println!("one"), _ => println!("other"), }
if let 1 = x { println!("one"); } else { println!("other"); } }
|