0%

rust-basic

数据类型

标量类型

复合类型

struct

定义struct

示例如下:

1
2
3
4
5
struct User {
name: String,
age: u32
email: String,
}

实例化struct

创建struct的实例,需要满足以下条件:

  • 为每个字段指定具体的值
  • 无需找声明的顺序进行指定
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
struct User {
name: String,
age: u32,
sex: String,
email: String,
}

fn main() {
let user1 = User {
name: String::from("Zhang San"),
age: 28,
sex: String::from("male"),
email: String::from("zhangsan123@163.com"),
};

println!("{} {} {} {}", user1.name, user1.age, user1.sex, user1.email);
}

注意:当字段名与字段值对应的变量名相同时,可以使用字段初始化简写的方式,示例如下

1
2
3
4
5
6
7
8
fn build_user(name: String, email: String) -> User {
User {
name,
age: 18,
sex: String::from("male"),
email,
}
}

struct更新语法

基于某个struct实例来创建一个新的实例时,可以使用struct更新语法进行创建,示例如下

1
2
3
4
5
6
7
8
9
10
11
12
13
let user1 = User {
name: String::from("Zhang San"),
age: 28,
sex: String::from("male"),
email: String::from("zhangsan123@163.com"),
};

// struct更新语法
let user2 = User {
name: String::from("Li Si"),
email: String::from("lisi456@163.com"),
..user1
};

struct数据所有权

示例中的name等元素使用了String而不是&str,则struct示例拥有其所有的数据,只要struct实例是有效的,name里面的字段数据也是有效的。

使用实例——计算长方形的面积

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#[derive(Debug)]
struct Rectangle {
width: u32,
height: u32,
}

fn cal_rectangle_area(rectangle: &Rectangle) -> u32 {
rectangle.width * rectangle.height
}

fn main() {
let rectangle = Rectangle {
width: 10,
height: 50,
};

println!("{:?}", rectangle);
println!("rectangle area: {}", cal_rectangle_area(&rectangle))
}

输出结果如下:

1
2
Rectangle { width: 10, height: 50 }
rectangle area: 500

Tuple Struct

可定义类似tuple的sturct,称作tuple struct

Tuple Strcut整体有名称,但里面的元素没有名称

适用于想给整个tuple起名,并且它不同于其他tuple,而且又不需要给每个元素起名的场景

定义Tuple Struct

示例如下:

1
2
3
4
5
strcut Color(i32, i32, i32)
strcut Point(i32, i32, i32)

let black = Color(0, 0, 0)
let origin = Point(0, 0, 0)

Unit-Like Struct

在rust中,没有任何字段的struct称作Unit-Like Struct

适用于需要在某个类型实现某个trait,但是在里面又没有想要存储的数据

struct的方法

方法与函数的相同之处:

  • fn关键字、名称、参数、返回值

方法与函数的不同之处:

  • 方法在struct(或enum、trait对象)的上下文中进行定义,需要在impl块中定义方法;
  • 方法的第一个参数时self,表示方法被调用的struct实例;
  • 方法调用的运算符:object.func();

以计算长方形面积为例,实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#[derive(Debug)]
struct Rectangle {
width: u32,
height: u32,
}

impl Rectangle {
fn cal_rectangle_area(&self) -> u32 {
self.width * self.height
}
}

fn main() {
let rectangle = Rectangle {
width: 10,
height: 50,
};

println!("{:?}", rectangle);
println!("rectangle area: {}", rectangle.cal_rectangle_area())
}

输出结果如下:

1
2
Rectangle { width: 10, height: 50 }
rectangle area: 500

关联函数

可以在在impl块里定义不把self作为第一个参数的函数,被称作关联函数,关联函数不是方法,例如String::from()

关联函数通常被用于构造器,示例如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#[derive(Debug)]
struct Rectangle {
width: u32,
height: u32,
}

impl Rectangle {
fn cal_rectangle_area(&self) -> u32 {
self.width * self.height
}

fn create_square(size: u32) -> Rectangle {
Rectangle { width: size, height: size }
}
}

fn main() {
let square = Rectangle::create_square(5);
println!("{}", square.cal_rectangle_area());
}

输出如下:5

枚举类型

实现一个结构体struct,用于存储IP地址信息,示例如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#[derive(Debug)]
enum IpAddrType {
IPv4,
IPv6,
}

struct IpAddrInfo {
ip_type: IpAddrType,
addr: String,
}

fn main() {
let route = IpAddrInfo {
ip_type: IpAddrType::IPv4,
addr: String::from("127.0.0.1"),
};

print!("{:?} {}", route.ip_type, route.addr);
}

输出结果如下:

1
IPv4 127.0.0.1

标准库中的IpAddr

枚举变体

将数据附加到枚举的变体中,示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
enum IpAddr {
IPv4(u8, u8, u8, u8),
IPv6(String),
}

fn main() {
let ipv4 = IpAddr::IPv4(127, 0, 0, 1);
let ipv6 = IpAddr::IPv6(String::from("AA22:BB11:1122:CDEF:1234:AA99:7654:7410"));

println!("ipv4: {:?}", ipv4);
println!("ipv6: {:?}", ipv6);
}

输出结果如下:

1
2
ipv4: IPv4(127, 0, 0, 1)
ipv6: IPv6("AA22:BB11:1122:CDEF:1234:AA99:7654:7410")

Option枚举

定义在标准库中,在Prelude(预导入模块)中,描述了某个值可能存在(某种类型)或者不存在的情况

在标准库中的定义如下:

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

使用示例如下:

1
2
3
4
5
6
fn main() {
let some_num = Some(5);
let some_str = Some("This a string.");

let absent_num: Option<i32> = None;
}

控制流运算符match

  • match匹配必须穷举所有可能的值
  • 可以使用通配符_,用于替代其他没列出的值,类似C语言switch/case中的default处理

示例如下,使用效果类似switch/case

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
enum Coin {
Penny,
Nickel,
Dime,
Quarter,
}

fn value_in_cents(coin: Coin) -> u8 {
match coin {
Coin::Penny => 1,
Coin::Nickel => 5,
Coin::Dime => 10,
Coin::Quarter => 25,
}
}

fn main() {
let coin = Coin::Nickel;
println!("{}", value_in_cents(coin));
}

绑定值的模式匹配

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
enum UsState {
Alabama,
Alaska,
}

enum Coin {
Penny,
Nickel,
Dime,
Quarter(UsState),
}

fn value_in_cents(coin: Coin) -> u8 {
match coin {
Coin::Penny => 1,
Coin::Nickel => 5,
Coin::Dime => 10,
Coin::Quarter(state) => {
println!("State quarter from {:?}", state);
25
}
}
}

fn main() {
let coin = Coin::Quarter(UsState::Alaska);
println!("{}", value_in_cents(coin));
}