本文的参考代码在这里

枚举 enum

基本概念

枚举为您提供了一种表示某个值是一组可能的值之一的方法。

  • 下面的代码定义了枚举 enum 类型,IpAddrKind v4和v6
  • 绑定枚举值时,须用 :: 绑定
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#[derive(Debug)]
enum IpAddrKind {
v4,
v6
}

fn main() {
// 创建变体实例, 用 :: 绑定值
let four = IpAddrKind::v4;
let six = IpAddrKind::v6;

route(four); // ip_kind -> v4
route(six); // ip_kind -> v6
}

fn route(ip_kind: IpAddrKind) {
println!("ip_kind -> {:?}", ip_kind);
}

我们创建一个上一节提到的 struct 结构体,对ip的实际地址用字符串进行存储:

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
#[derive(Debug)]
enum IpAddrKind {
v4,
v6
}

#[derive(Debug)]
struct IpAddr {
kind: IpAddrKind,
address: String
}

fn main() {
let home = IpAddr {
kind: IpAddrKind::v4,
address: String::from("127.0.0.1"),
};

let loopback = IpAddr {
kind: IpAddrKind::v6,
address: String::from("::1"),
};

route(home); // ip_kind -> IpAddr { kind: v4, address: "127.0.0.1" }
route(loopback); // ip_kind -> IpAddr { kind: v6, address: "::1" }
}

fn route(ip_kind: IpAddr) {
println!("ip_kind -> {:?}", ip_kind);
}

enum 可独自定义每个成员的数据类型

但上面的代码可以让 enum 直接存储类型为 String, 省去更多代码,可以改写如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
#[derive(Debug)]
enum IpAddrKind {
v4(String),
v6(String)
}

fn main() {
let home = IpAddrKind::v4(String::from("127.0.0.1"));
let loopback = IpAddrKind::v6(String::from("::1"));

println!("home {:?}", home); // home v4("127.0.0.1")
println!("loopback {:?}", loopback); // loopback v6("::1")
}

甚至可以再细化, 做到结构体无法完成的任务,例如ipv4一般是4个8 bit的 数值,定义类型时可和ipv6区分开来:

1
2
3
4
5
6
7
8
9
10
11
12
13
#[derive(Debug)]
enum IpAddrKind {
v4(u8, u8, u8, u8),
v6(String)
}

fn main() {
let home = IpAddrKind::v4(String::from(127, 0, 0, 1));
let loopback = IpAddrKind::v6(String::from("::1"));

println!("home {:?}", home); // home v4("127.0.0.1")
println!("loopback {:?}", loopback); // loopback v6("::1")
}

其实我们在标准库里,可以看到一个专门定义ip的结构体,可以用来这样表达enum

1
2
3
4
5
6
7
8
9
10
11
12
struct Ipv4Addr {
// --snip--
}

struct Ipv6Addr {
// --snip--
}

enum IpAddr {
V4(Ipv4Addr),
V6(Ipv6Addr),
}

rust 里没有 null 值概念,null 的问题在于,如果您尝试将空值用作非空值,则会收到某种错误。所以用 None代替,即无值。他在标准库的定义如下:

1
2
3
4
enum Option<T> {
None,
Some(T),
}