复合数据类型
复合类型(compound type)可以将多个不同类型的值组合为一个类型。
Rust提供了两种内置的基础复合类型:元组(tuple)和数组(array)。
元祖类型
声明元祖
元祖( tuple )类型,就是将其他类型的值,使用圆括号包裹起来,组内的各个值通过 ,
进行分割。
// 定义了一个元祖类型,包含4个值
let tup = (10, 10.1, 'a', true);
在声明元素类型的变量时,可以指定类型。元祖类型是通过圆括号语法声明:
let tup:(i32, f64, char, bool) = (10, 10.1, 'a', true);
访问
通过解构赋值/模式匹配的方式,来获得元祖内的值:
fn main() {
// 定义了一个元祖类型,包含4个值
let tup = (10, 10.1, 'a', true);
// 使用解构赋值时,需要将元素的所有内容都解构出来
let (a, b, c, d) = tup;
println!("{} {} {} {}",a, b, c, d); // 10 10.1 a true
}
或者通过类似数组的索引的方式去取值,但是要通过 .
而不是 []
:
// 定义了一个元祖类型,包含4个值
let tup = (10, 10.1, 'a', true);
println!("{}", tup.0); // 10
元组的长度是固定的,在声明变量时就确定好了。在声明结束后增加或减少其中的元素数量都会报错。
数组类型
数组也是多个值的集合,它的特点是:
- 数组大小固定,在声明时确定
- 元素均为同类型
- 默认不可变(还有一种动态数组,是可变的。先不涉及。)
声明数组
let arr = [1, 2, 3, 4];
在声明元素类型的变量时,可以指定类型。数组类型是通过方括号语法声明:
let arr:[i32; 4] = [1, 2, 3, 4];
前面的 i32 表示元素类型,后面的数字表示元素的个数。
访问数组元素
使用索引来访问数组的元素:
let arr = [1, 2, 3, 4];
println!("{}", arr[1]); // 2
越界访问
和 JS 的不同之处,Rust 的数组是存储在栈内存中,性能较好。而动态数组是存在堆内存中的。
另一种不同之处,是 Rust 中访问一个不存在的元素时,会报错;而 JS 中则返回一个 undefined。
let arr = [1, 2, 3, 4];
println!("{}", arr[10]); // 2
这种错误叫做 越界访问,是一种只发生在运行时才能检出的错误。
结构体类型
结构体(struct)把多个类型组合到一起,每个元素都有自己的名字,有点像是 TS 中的接口。
通过 .
操作符可以访问结构体实例内部的字段值。
// 使用 struct 关键字声明一个结构体类型
struct Point {
x: i32,
y: i32,
}
fn main() {
// 声明一个 Point 类型的变量
let p = Point{
x: 10,
y: 20
};
println!("{} {}", p.x, p.y);
}
小结
本文介绍了 Rust 中的三种复合类型,元组,数组和结构体。除了一些细节地方和其他语言有些不同,无论是声明方式还是使用方式,大都差不多。