Skip to content

Rust - 元组

元组(tuple)是一种通用的复合数据类型,用于将多种类型的值组合成一个复合类型。元组具有固定长度:一旦声明,它们的大小就不能增长或缩小。

当你想要组合一些相关信息,而又不想额外创建完整的 struct 时,元组会非常有用。

你可以通过在括号内写入逗号分隔的值列表来创建元组。元组中的每个位置都有一个类型,并且元组中不同值的数据类型不必相同。

你可以使用点号(.)后跟索引来直接访问元组元素。第一个索引是 0。

fn main() {
// 创建带类型注解的元组
let user_data: (String, u32, bool) = (String::from("Alice"), 30, true);
// 通过索引访问元素
let user_name = &user_data.0;
let user_age = user_data.1;
println!("User: {}, Age: {}", user_name, user_age);
// 你可以使用调试格式化器 `{:?}` 来打印整个元组
println!("Full user data: {:?}", user_data);
}
User: Alice, Age: 30
Full user data: ("Alice", 30, true)

解构(Destructuring)是一种将元组拆分为其各个部分的便捷方式。你可以使用 let 模式来实现这一点,它会为元组的每个元素创建变量。

fn main() {
let http_status = (404, "Not Found");
// 将元组解构为两个变量
let (status_code, status_message) = http_status;
println!("The status code is {}", status_code);
println!("The status message is '{}'", status_message);
// 注意:如果原始元组 `http_status` 的类型是 `Copy`,它仍然可用。
// 如果它包含 `String` 等非 `Copy` 类型,则值会被移动。
println!("Original tuple: {:?}", http_status);
}
The status code is 404
The status message is 'Not Found'
Original tuple: (404, "Not Found")

元组的一个常见且惯用的用法是从函数返回多个值。如果结构简单且只在一个地方使用,这通常比返回 struct 更简洁。

// 此函数计算句子的长度和第一个单词。
// 它返回一个包含 usize 和 String 的元组。
fn calculate_length_and_first_word(s: String) -> (usize, String) {
let length = s.len();
let first_word = s.split_whitespace().next().unwrap_or("").to_string();
(length, first_word) // 返回元组
}
fn main() {
let sentence = String::from("Rust programming is fun");
let (len, word) = calculate_length_and_first_word(sentence);
println!("The sentence has {} bytes.", len);
println!("The first word is '{}'.", word);
// 在这里尝试使用 `sentence` 会失败,因为它已被移动到函数中。
// println!("{}", sentence); // 错误:值在移动后在此处被借用
}

元组和结构体相似,但有不同的理想用例:

  • 何时使用元组: 当你有一个小型、固定大小的,包含相关但类型不同的数据集合,并且每个元素的含义仅从其位置就清楚时。返回错误码和结果是一个经典示例。
  • 何时使用结构体: 当你的数据更复杂时。为每个字段命名可使代码更具可读性和可维护性。如果你希望在多个函数之间传递此数据结构,struct 几乎总是更好的选择。

有一个没有元素的特殊元组,写作 ()。这被称为单元类型(unit type),它只有一个值,也写作 ()。没有显式 -> 返回类型的函数会隐式返回单元类型。它表示一个空或无值的返回。

fn does_not_return_a_value() {
println!("I return the unit type implicitly!");
}
fn main() {
let result = does_not_return_a_value();
// 这里的 `result` 具有值 `()` 和类型 `()`
// 这不是很实用,但能演示这个概念。
}