讲解
复合类型把多个值组合成一个。Rust 内置两种:元组(tuple)和数组(array)。元组是长度固定、元素类型可以各不相同的组合:let tup: (i32, f64, &str) = (500, 6.4, "元组")。取值有两种方式:模式解构 let (x, y, z) = tup,或者点号加下标 tup.0。函数想返回多个值时,返回元组是最轻量的写法。空元组 () 叫单元类型,「没有有意义的返回值」的函数实际返回的就是它。
数组是长度固定、元素类型必须相同的序列,写在栈上:let a: [i32; 5] = [1, 2, 3, 4, 5],类型标注里 [i32; 5] 的分号后就是长度——长度是类型的一部分,[i32; 3] 和 [i32; 4] 是两个不同的类型。重复初始化有语法糖:let zeros = [0; 10] 得到十个 0。
数组长度编译期写死,这个限制在真实业务里很快会遇到天花板——元素个数要随运行变化时用 Vec(动态数组,第 16 章)。数组的主场是元素个数确实固定的场景:一周七天、RGBA 四通道、固定大小的缓冲区。下标访问 arr[i] 越界会 panic(编译期检查不了运行时下标),想要安全访问用 .get(i),越界时得到 None 而不是崩溃。
示例
元组的解构与下标访问:
fn main() {
let tup: (i32, f64, &str) = (500, 6.4, "元组");
let (x, y, z) = tup; // 解构
println!("x={x}, y={y}, z={z}");
println!("第一个元素是 {}", tup.0);
// 函数用元组一次返回多个值
fn min_max(a: i32, b: i32) -> (i32, i32) {
if a < b { (a, b) } else { (b, a) }
}
let (lo, hi) = min_max(9, 3);
assert_eq!((lo, hi), (3, 9));
}
数组的初始化、遍历与安全访问:
fn main() {
let arr: [i32; 5] = [10, 20, 30, 40, 50];
let same = [7; 3]; // [7, 7, 7]
let mut sum = 0;
for n in arr {
sum += n;
}
assert_eq!(sum, 150);
assert_eq!(same, [7, 7, 7]);
// .get 越界返回 None,不 panic
match arr.get(10) {
Some(v) => println!("第 10 项是 {v}"),
None => println!("下标 10 越界了(数组长度 {})", arr.len()),
}
}
常见坑
- arr[i] 越界 panic:下标来自运行时数据(用户输入、计算结果)时,用 .get(i) 拿到 Option 再处理,别让程序崩在用户手里。
- 以为数组能变长:[i32; 5] 永远是 5 个元素,push/append 不存在;要变长请换 Vec。
- 混淆 (x) 和 (x,):(5) 只是带括号的 5,单元素元组必须写 (5,)——这个逗号是语法的一部分。
- 元组当结构体用:元素超过三四个、或需要给字段起名时,元组的可读性会崩,该上结构体(第 12 章)。
小结
元组:固定长度、类型可混合,解构或 .0 取值;数组:固定长度、类型统一,长度写进类型,.get() 是安全访问。需要变长请期待第 16 章的 Vec。下一章讲函数。