本章目标
通过本章学习,你将掌握: - 结构体的定义和使用 - 结构体方法和关联函数 - 元组结构体和单元结构体 - 枚举类型的定义和使用 - 模式匹配和match表达式 - Option和Result枚举 - 复杂数据结构的设计
5.1 结构体基础
定义和实例化结构体
// 定义用户结构体
struct User {
username: String,
email: String,
sign_in_count: u64,
active: bool,
}
// 定义矩形结构体
struct Rectangle {
width: u32,
height: u32,
}
// 定义颜色结构体
struct Color {
red: u8,
green: u8,
blue: u8,
}
fn main() {
println!("🏗️ 结构体基础示例");
println!("==================");
// 创建结构体实例
let user1 = User {
email: String::from("alice@example.com"),
username: String::from("alice"),
active: true,
sign_in_count: 1,
};
println!("用户信息:");
println!(" 用户名: {}", user1.username);
println!(" 邮箱: {}", user1.email);
println!(" 活跃状态: {}", user1.active);
println!(" 登录次数: {}", user1.sign_in_count);
// 创建可变结构体实例
let mut user2 = User {
email: String::from("bob@example.com"),
username: String::from("bob"),
active: true,
sign_in_count: 0,
};
// 修改字段值
user2.email = String::from("bob.new@example.com");
user2.sign_in_count += 1;
println!("\n修改后的用户信息:");
println!(" 用户名: {}", user2.username);
println!(" 新邮箱: {}", user2.email);
println!(" 登录次数: {}", user2.sign_in_count);
// 使用函数创建结构体
let user3 = build_user(
String::from("charlie@example.com"),
String::from("charlie")
);
println!("\n通过函数创建的用户:");
println!(" 用户名: {}", user3.username);
println!(" 邮箱: {}", user3.email);
// 结构体更新语法
let user4 = User {
email: String::from("david@example.com"),
username: String::from("david"),
..user1 // 使用user1的其他字段值
};
println!("\n使用更新语法创建的用户:");
println!(" 用户名: {}", user4.username);
println!(" 邮箱: {}", user4.email);
println!(" 活跃状态: {}", user4.active);
// 创建矩形和颜色
demonstrate_other_structs();
}
// 构建用户的函数
fn build_user(email: String, username: String) -> User {
User {
email, // 字段初始化简写
username, // 字段初始化简写
active: true,
sign_in_count: 1,
}
}
fn demonstrate_other_structs() {
println!("\n其他结构体示例:");
// 创建矩形
let rect = Rectangle {
width: 30,
height: 50,
};
println!("矩形: {}x{}", rect.width, rect.height);
println!("面积: {}", rect.width * rect.height);
// 创建颜色
let red = Color {
red: 255,
green: 0,
blue: 0,
};
let green = Color {
red: 0,
green: 255,
blue: 0,
};
println!("红色: RGB({}, {}, {})", red.red, red.green, red.blue);
println!("绿色: RGB({}, {}, {})", green.red, green.green, green.blue);
// 混合颜色
let purple = Color {
red: (red.red + green.red) / 2,
green: (red.green + green.green) / 2,
blue: (red.blue + green.blue) / 2,
};
println!("混合色: RGB({}, {}, {})", purple.red, purple.green, purple.blue);
}
rustc struct_basics.rs && ./struct_basics
元组结构体和单元结构体
// 元组结构体
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
// 单元结构体
struct AlwaysEqual;
// 新类型模式
struct UserId(u32);
struct UserName(String);
struct Email(String);
fn main() {
println!("📦 元组结构体和单元结构体");
println!("=============================");
// 元组结构体示例
let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);
println!("黑色: ({}, {}, {})", black.0, black.1, black.2);
println!("原点: ({}, {}, {})", origin.0, origin.1, origin.2);
// 注意:Color和Point是不同的类型,即使结构相同
// let color_point: Point = black; // 编译错误!
// 解构元组结构体
let Color(r, g, b) = black;
println!("解构黑色: r={}, g={}, b={}", r, g, b);
// 单元结构体
let subject = AlwaysEqual;
let another_subject = AlwaysEqual;
println!("单元结构体创建成功");
// 新类型模式示例
demonstrate_newtype_pattern();
// 更多元组结构体示例
demonstrate_more_tuple_structs();
}
fn demonstrate_newtype_pattern() {
println!("\n新类型模式:");
// 使用新类型包装原始类型
let user_id = UserId(12345);
let user_name = UserName(String::from("alice"));
let email = Email(String::from("alice@example.com"));
println!("用户ID: {}", user_id.0);
println!("用户名: {}", user_name.0);
println!("邮箱: {}", email.0);
// 新类型提供类型安全
// let wrong_id: UserId = 12345; // 编译错误!必须使用UserId(12345)
// 函数可以明确参数类型
process_user_id(user_id);
process_user_name(user_name);
process_email(email);
}
fn process_user_id(id: UserId) {
println!("处理用户ID: {}", id.0);
}
fn process_user_name(name: UserName) {
println!("处理用户名: {}", name.0);
}
fn process_email(email: Email) {
println!("处理邮箱: {}", email.0);
}
fn demonstrate_more_tuple_structs() {
println!("\n更多元组结构体示例:");
// 2D和3D向量
struct Vector2D(f64, f64);
struct Vector3D(f64, f64, f64);
let v2d = Vector2D(3.0, 4.0);
let v3d = Vector3D(1.0, 2.0, 3.0);
println!("2D向量: ({}, {})", v2d.0, v2d.1);
println!("3D向量: ({}, {}, {})", v3d.0, v3d.1, v3d.2);
// 计算向量长度
let length_2d = (v2d.0 * v2d.0 + v2d.1 * v2d.1).sqrt();
let length_3d = (v3d.0 * v3d.0 + v3d.1 * v3d.1 + v3d.2 * v3d.2).sqrt();
println!("2D向量长度: {:.2}", length_2d);
println!("3D向量长度: {:.2}", length_3d);
// 温度类型
struct Celsius(f64);
struct Fahrenheit(f64);
let temp_c = Celsius(25.0);
let temp_f = Fahrenheit(77.0);
println!("摄氏温度: {}°C", temp_c.0);
println!("华氏温度: {}°F", temp_f.0);
// 温度转换
let converted_f = Fahrenheit(temp_c.0 * 9.0 / 5.0 + 32.0);
let converted_c = Celsius((temp_f.0 - 32.0) * 5.0 / 9.0);
println!("{}°C = {}°F", temp_c.0, converted_f.0);
println!("{}°F = {:.1}°C", temp_f.0, converted_c.0);
}
rustc tuple_unit_structs.rs && ./tuple_unit_structs
5.2 方法和关联函数
定义方法
#[derive(Debug)] // 自动实现Debug trait
struct Rectangle {
width: u32,
height: u32,
}
impl Rectangle {
// 关联函数(类似静态方法)
fn new(width: u32, height: u32) -> Rectangle {
Rectangle { width, height }
}
fn square(size: u32) -> Rectangle {
Rectangle {
width: size,
height: size,
}
}
// 方法(需要self参数)
fn area(&self) -> u32 {
self.width * self.height
}
fn perimeter(&self) -> u32 {
2 * (self.width + self.height)
}
fn can_hold(&self, other: &Rectangle) -> bool {
self.width > other.width && self.height > other.height
}
// 可变方法
fn scale(&mut self, factor: u32) {
self.width *= factor;
self.height *= factor;
}
fn set_width(&mut self, width: u32) {
self.width = width;
}
fn set_height(&mut self, height: u32) {
self.height = height;
}
// 获取所有权的方法
fn into_square(self) -> Rectangle {
let size = std::cmp::min(self.width, self.height);
Rectangle::square(size)
}
}
#[derive(Debug)]
struct Circle {
radius: f64,
}
impl Circle {
fn new(radius: f64) -> Circle {
Circle { radius }
}
fn area(&self) -> f64 {
std::f64::consts::PI * self.radius * self.radius
}
fn circumference(&self) -> f64 {
2.0 * std::f64::consts::PI * self.radius
}
fn scale(&mut self, factor: f64) {
self.radius *= factor;
}
fn diameter(&self) -> f64 {
self.radius * 2.0
}
}
fn main() {
println!("🔧 结构体方法示例");
println!("==================");
// 使用关联函数创建实例
let rect1 = Rectangle::new(30, 50);
let rect2 = Rectangle::new(10, 40);
let square = Rectangle::square(25);
println!("矩形1: {:?}", rect1);
println!("矩形2: {:?}", rect2);
println!("正方形: {:?}", square);
// 调用方法
println!("\n矩形1信息:");
println!(" 面积: {}", rect1.area());
println!(" 周长: {}", rect1.perimeter());
println!("\n正方形信息:");
println!(" 面积: {}", square.area());
println!(" 周长: {}", square.perimeter());
// 比较矩形
println!("\n矩形比较:");
println!(" 矩形1能容纳矩形2吗? {}", rect1.can_hold(&rect2));
println!(" 矩形2能容纳矩形1吗? {}", rect2.can_hold(&rect1));
println!(" 正方形能容纳矩形2吗? {}", square.can_hold(&rect2));
// 修改矩形
let mut rect3 = Rectangle::new(20, 30);
println!("\n修改前的矩形3: {:?}", rect3);
println!("面积: {}", rect3.area());
rect3.scale(2);
println!("放大2倍后: {:?}", rect3);
println!("面积: {}", rect3.area());
rect3.set_width(100);
rect3.set_height(50);
println!("设置新尺寸后: {:?}", rect3);
// 转换为正方形(消费原矩形)
let new_square = rect3.into_square();
println!("转换为正方形: {:?}", new_square);
// println!("{:?}", rect3); // 错误!rect3已被移动
// 圆形示例
demonstrate_circle_methods();
}
fn demonstrate_circle_methods() {
println!("\n圆形方法示例:");
let mut circle = Circle::new(5.0);
println!("圆形: {:?}", circle);
println!("圆形信息:");
println!(" 半径: {}", circle.radius);
println!(" 直径: {:.2}", circle.diameter());
println!(" 面积: {:.2}", circle.area());
println!(" 周长: {:.2}", circle.circumference());
// 放大圆形
circle.scale(1.5);
println!("\n放大1.5倍后:");
println!(" 半径: {:.2}", circle.radius);
println!(" 面积: {:.2}", circle.area());
println!(" 周长: {:.2}", circle.circumference());
// 创建不同大小的圆
let circles = vec![
Circle::new(1.0),
Circle::new(2.5),
Circle::new(4.0),
Circle::new(7.5),
];
println!("\n多个圆形:");
for (i, circle) in circles.iter().enumerate() {
println!(" 圆{}:半径={:.1}, 面积={:.2}",
i + 1, circle.radius, circle.area());
}
}
rustc struct_methods.rs && ./struct_methods
多个impl块
#[derive(Debug)]
struct Calculator {
value: f64,
}
// 第一个impl块:基本操作
impl Calculator {
fn new(value: f64) -> Calculator {
Calculator { value }
}
fn get_value(&self) -> f64 {
self.value
}
fn set_value(&mut self, value: f64) {
self.value = value;
}
fn reset(&mut self) {
self.value = 0.0;
}
}
// 第二个impl块:算术操作
impl Calculator {
fn add(&mut self, other: f64) -> &mut Self {
self.value += other;
self
}
fn subtract(&mut self, other: f64) -> &mut Self {
self.value -= other;
self
}
fn multiply(&mut self, other: f64) -> &mut Self {
self.value *= other;
self
}
fn divide(&mut self, other: f64) -> &mut Self {
if other != 0.0 {
self.value /= other;
} else {
println!("警告:除零操作,值保持不变");
}
self
}
}
// 第三个impl块:高级操作
impl Calculator {
fn power(&mut self, exponent: f64) -> &mut Self {
self.value = self.value.powf(exponent);
self
}
fn square_root(&mut self) -> &mut Self {
if self.value >= 0.0 {
self.value = self.value.sqrt();
} else {
println!("警告:负数开方,值保持不变");
}
self
}
fn absolute(&mut self) -> &mut Self {
self.value = self.value.abs();
self
}
fn negate(&mut self) -> &mut Self {
self.value = -self.value;
self
}
}
// 第四个impl块:比较和格式化
impl Calculator {
fn is_positive(&self) -> bool {
self.value > 0.0
}
fn is_negative(&self) -> bool {
self.value < 0.0
}
fn is_zero(&self) -> bool {
self.value == 0.0
}
fn round(&mut self, decimal_places: u32) -> &mut Self {
let factor = 10.0_f64.powi(decimal_places as i32);
self.value = (self.value * factor).round() / factor;
self
}
fn format(&self, decimal_places: usize) -> String {
format!("{:.1$}", self.value, decimal_places)
}
}
fn main() {
println!("🧮 多个impl块示例");
println!("==================");
// 创建计算器
let mut calc = Calculator::new(10.0);
println!("初始值: {}", calc.get_value());
// 链式调用
calc.add(5.0)
.multiply(2.0)
.subtract(10.0)
.divide(2.0);
println!("链式计算结果: {}", calc.get_value());
// 高级操作
calc.set_value(16.0);
println!("\n设置值为16.0");
calc.square_root();
println!("开方后: {}", calc.get_value());
calc.power(3.0);
println!("立方后: {}", calc.get_value());
// 比较操作
println!("\n比较操作:");
println!(" 是正数吗? {}", calc.is_positive());
println!(" 是负数吗? {}", calc.is_negative());
println!(" 是零吗? {}", calc.is_zero());
// 格式化
calc.set_value(3.14159265);
println!("\n格式化示例:");
println!(" 原值: {}", calc.get_value());
println!(" 2位小数: {}", calc.format(2));
println!(" 4位小数: {}", calc.format(4));
calc.round(2);
println!(" 四舍五入到2位: {}", calc.get_value());
// 复杂计算示例
demonstrate_complex_calculations();
}
fn demonstrate_complex_calculations() {
println!("\n复杂计算示例:");
// 计算圆的面积:π * r²
let mut calc = Calculator::new(5.0); // 半径
calc.power(2.0) // r²
.multiply(std::f64::consts::PI); // π * r²
println!("半径为5的圆面积: {:.2}", calc.get_value());
// 计算二次方程的判别式:b² - 4ac
// 例如:2x² + 3x - 1 = 0
let a = 2.0;
let b = 3.0;
let c = -1.0;
calc.set_value(b)
.power(2.0) // b²
.subtract(4.0 * a * c); // b² - 4ac
println!("二次方程 {}x² + {}x + {} = 0 的判别式: {:.2}",
a, b, c, calc.get_value());
if calc.is_positive() {
println!("有两个实根");
// 计算根
let discriminant = calc.get_value();
calc.square_root(); // √(b² - 4ac)
let sqrt_discriminant = calc.get_value();
let root1 = (-b + sqrt_discriminant) / (2.0 * a);
let root2 = (-b - sqrt_discriminant) / (2.0 * a);
println!("根1: {:.3}", root1);
println!("根2: {:.3}", root2);
} else if calc.is_zero() {
println!("有一个重根");
let root = -b / (2.0 * a);
println!("根: {:.3}", root);
} else {
println!("没有实根");
}
// 计算复利:A = P(1 + r)^t
let principal = 1000.0; // 本金
let rate = 0.05; // 年利率5%
let time = 10.0; // 10年
calc.set_value(1.0 + rate)
.power(time)
.multiply(principal);
println!("\n复利计算:");
println!("本金: ${:.2}", principal);
println!("年利率: {:.1}%", rate * 100.0);
println!("时间: {:.0}年", time);
println!("最终金额: ${:.2}", calc.get_value());
println!("利息: ${:.2}", calc.get_value() - principal);
}
rustc multiple_impl_blocks.rs && ./multiple_impl_blocks
5.3 枚举类型
基本枚举
// 基本枚举
#[derive(Debug)]
enum Direction {
North,
South,
East,
West,
}
// 带数据的枚举
#[derive(Debug)]
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(i32, i32, i32),
}
// IP地址枚举
#[derive(Debug)]
enum IpAddr {
V4(u8, u8, u8, u8),
V6(String),
}
// 几何形状枚举
#[derive(Debug)]
enum Shape {
Circle { radius: f64 },
Rectangle { width: f64, height: f64 },
Triangle { base: f64, height: f64 },
}
impl Direction {
fn opposite(&self) -> Direction {
match self {
Direction::North => Direction::South,
Direction::South => Direction::North,
Direction::East => Direction::West,
Direction::West => Direction::East,
}
}
fn to_string(&self) -> &str {
match self {
Direction::North => "北",
Direction::South => "南",
Direction::East => "东",
Direction::West => "西",
}
}
}
impl Message {
fn process(&self) {
match self {
Message::Quit => {
println!("退出程序");
}
Message::Move { x, y } => {
println!("移动到坐标 ({}, {})", x, y);
}
Message::Write(text) => {
println!("写入文本: {}", text);
}
Message::ChangeColor(r, g, b) => {
println!("改变颜色为 RGB({}, {}, {})", r, g, b);
}
}
}
}
impl Shape {
fn area(&self) -> f64 {
match self {
Shape::Circle { radius } => {
std::f64::consts::PI * radius * radius
}
Shape::Rectangle { width, height } => {
width * height
}
Shape::Triangle { base, height } => {
0.5 * base * height
}
}
}
fn perimeter(&self) -> f64 {
match self {
Shape::Circle { radius } => {
2.0 * std::f64::consts::PI * radius
}
Shape::Rectangle { width, height } => {
2.0 * (width + height)
}
Shape::Triangle { base, height } => {
// 假设是等腰三角形
let side = (height * height + (base / 2.0) * (base / 2.0)).sqrt();
base + 2.0 * side
}
}
}
}
fn main() {
println!("🔢 枚举基础示例");
println!("===============");
// 基本枚举使用
let directions = vec![
Direction::North,
Direction::South,
Direction::East,
Direction::West,
];
println!("方向及其相反方向:");
for direction in &directions {
println!(" {} -> {}",
direction.to_string(),
direction.opposite().to_string());
}
// 带数据的枚举
let messages = vec![
Message::Quit,
Message::Move { x: 10, y: 20 },
Message::Write(String::from("Hello, Rust!")),
Message::ChangeColor(255, 0, 128),
];
println!("\n处理消息:");
for message in &messages {
message.process();
}
// IP地址枚举
let addresses = vec![
IpAddr::V4(127, 0, 0, 1),
IpAddr::V4(192, 168, 1, 1),
IpAddr::V6(String::from("::1")),
IpAddr::V6(String::from("2001:db8::1")),
];
println!("\nIP地址:");
for (i, addr) in addresses.iter().enumerate() {
match addr {
IpAddr::V4(a, b, c, d) => {
println!(" 地址{}: IPv4 {}.{}.{}.{}", i + 1, a, b, c, d);
}
IpAddr::V6(addr) => {
println!(" 地址{}: IPv6 {}", i + 1, addr);
}
}
}
// 几何形状枚举
demonstrate_shapes();
}
fn demonstrate_shapes() {
println!("\n几何形状计算:");
let shapes = vec![
Shape::Circle { radius: 5.0 },
Shape::Rectangle { width: 10.0, height: 6.0 },
Shape::Triangle { base: 8.0, height: 6.0 },
];
for (i, shape) in shapes.iter().enumerate() {
println!("\n形状{}:", i + 1);
match shape {
Shape::Circle { radius } => {
println!(" 类型: 圆形,半径: {}", radius);
}
Shape::Rectangle { width, height } => {
println!(" 类型: 矩形,宽: {},高: {}", width, height);
}
Shape::Triangle { base, height } => {
println!(" 类型: 三角形,底: {},高: {}", base, height);
}
}
println!(" 面积: {:.2}", shape.area());
println!(" 周长: {:.2}", shape.perimeter());
}
// 计算总面积
let total_area: f64 = shapes.iter().map(|shape| shape.area()).sum();
println!("\n所有形状的总面积: {:.2}", total_area);
// 找到最大面积的形状
if let Some((index, shape)) = shapes
.iter()
.enumerate()
.max_by(|(_, a), (_, b)| a.area().partial_cmp(&b.area()).unwrap())
{
println!("最大面积的形状是第{}个,面积: {:.2}", index + 1, shape.area());
}
}
rustc enum_basics.rs && ./enum_basics
Option枚举
fn main() {
println!("🎯 Option枚举示例");
println!("==================");
// Option的基本使用
let some_number = Some(5);
let some_string = Some("hello");
let absent_number: Option<i32> = None;
println!("some_number: {:?}", some_number);
println!("some_string: {:?}", some_string);
println!("absent_number: {:?}", absent_number);
// 使用match处理Option
let x = Some(5);
let y = None;
println!("\n使用match处理Option:");
match x {
Some(value) => println!("x有值: {}", value),
None => println!("x没有值"),
}
match y {
Some(value) => println!("y有值: {}", value),
None => println!("y没有值"),
}
// Option的方法
demonstrate_option_methods();
// 实际应用示例
demonstrate_practical_examples();
// 链式操作
demonstrate_option_chaining();
}
fn demonstrate_option_methods() {
println!("\nOption的常用方法:");
let some_value = Some(42);
let no_value: Option<i32> = None;
// is_some() 和 is_none()
println!("some_value.is_some(): {}", some_value.is_some());
println!("some_value.is_none(): {}", some_value.is_none());
println!("no_value.is_some(): {}", no_value.is_some());
println!("no_value.is_none(): {}", no_value.is_none());
// unwrap() - 危险!只在确定有值时使用
println!("some_value.unwrap(): {}", some_value.unwrap());
// println!("no_value.unwrap(): {}", no_value.unwrap()); // 会panic!
// unwrap_or() - 提供默认值
println!("some_value.unwrap_or(0): {}", some_value.unwrap_or(0));
println!("no_value.unwrap_or(0): {}", no_value.unwrap_or(0));
// unwrap_or_else() - 使用闭包计算默认值
println!("no_value.unwrap_or_else(|| 100): {}",
no_value.unwrap_or_else(|| 100));
// map() - 转换Option中的值
let doubled = some_value.map(|x| x * 2);
let doubled_none = no_value.map(|x| x * 2);
println!("some_value.map(|x| x * 2): {:?}", doubled);
println!("no_value.map(|x| x * 2): {:?}", doubled_none);
// and_then() - 链式操作
let result = some_value.and_then(|x| {
if x > 40 {
Some(x * 2)
} else {
None
}
});
println!("条件链式操作结果: {:?}", result);
// filter() - 过滤值
let filtered = some_value.filter(|&x| x > 50);
let filtered2 = some_value.filter(|&x| x > 30);
println!("some_value.filter(|&x| x > 50): {:?}", filtered);
println!("some_value.filter(|&x| x > 30): {:?}", filtered2);
}
fn demonstrate_practical_examples() {
println!("\n实际应用示例:");
// 查找数组中的元素
let numbers = vec![1, 3, 5, 7, 9, 11, 13];
let found = find_number(&numbers, 7);
let not_found = find_number(&numbers, 8);
println!("查找7: {:?}", found);
println!("查找8: {:?}", not_found);
// 安全的除法
println!("\n安全除法:");
println!("10 / 2 = {:?}", safe_divide(10.0, 2.0));
println!("10 / 0 = {:?}", safe_divide(10.0, 0.0));
// 解析字符串为数字
println!("\n字符串解析:");
let valid_number = parse_number("42");
let invalid_number = parse_number("abc");
println!("解析'42': {:?}", valid_number);
println!("解析'abc': {:?}", invalid_number);
// 获取数组的第一个和最后一个元素
let empty_vec: Vec<i32> = vec![];
let non_empty_vec = vec![1, 2, 3, 4, 5];
println!("\n数组元素访问:");
println!("空数组的第一个元素: {:?}", get_first(&empty_vec));
println!("非空数组的第一个元素: {:?}", get_first(&non_empty_vec));
println!("非空数组的最后一个元素: {:?}", get_last(&non_empty_vec));
}
fn find_number(numbers: &[i32], target: i32) -> Option<usize> {
for (index, &number) in numbers.iter().enumerate() {
if number == target {
return Some(index);
}
}
None
}
fn safe_divide(a: f64, b: f64) -> Option<f64> {
if b != 0.0 {
Some(a / b)
} else {
None
}
}
fn parse_number(s: &str) -> Option<i32> {
s.parse().ok()
}
fn get_first<T>(vec: &[T]) -> Option<&T> {
vec.first()
}
fn get_last<T>(vec: &[T]) -> Option<&T> {
vec.last()
}
fn demonstrate_option_chaining() {
println!("\nOption链式操作:");
// 复杂的链式操作示例
let input = "42";
let result = parse_number(input)
.map(|n| n * 2) // 乘以2
.filter(|&n| n > 50) // 只保留大于50的
.map(|n| format!("结果: {}", n)); // 格式化为字符串
println!("处理'42': {:?}", result);
let input2 = "100";
let result2 = parse_number(input2)
.map(|n| n * 2)
.filter(|&n| n > 50)
.map(|n| format!("结果: {}", n));
println!("处理'100': {:?}", result2);
// 组合多个Option
let a = Some(5);
let b = Some(10);
let c: Option<i32> = None;
let sum_ab = add_options(a, b);
let sum_ac = add_options(a, c);
println!("\n组合Option:");
println!("Some(5) + Some(10) = {:?}", sum_ab);
println!("Some(5) + None = {:?}", sum_ac);
// 使用?操作符的模拟(在函数中)
let calculation_result = complex_calculation(Some(10), Some(5));
println!("复杂计算结果: {:?}", calculation_result);
let calculation_result2 = complex_calculation(Some(10), None);
println!("复杂计算结果2: {:?}", calculation_result2);
}
fn add_options(a: Option<i32>, b: Option<i32>) -> Option<i32> {
match (a, b) {
(Some(x), Some(y)) => Some(x + y),
_ => None,
}
// 或者使用更简洁的方式:
// a.and_then(|x| b.map(|y| x + y))
}
fn complex_calculation(a: Option<i32>, b: Option<i32>) -> Option<String> {
let sum = add_options(a, b)?; // 如果任一为None,直接返回None
let doubled = sum * 2;
let result = format!("计算结果: {}", doubled);
Some(result)
}
rustc option_enum.rs && ./option_enum
Result枚举
use std::fs::File;
use std::io::{self, Read};
use std::num::ParseIntError;
// 自定义错误类型
#[derive(Debug)]
enum MathError {
DivisionByZero,
NegativeSquareRoot,
InvalidInput,
}
impl std::fmt::Display for MathError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
MathError::DivisionByZero => write!(f, "除零错误"),
MathError::NegativeSquareRoot => write!(f, "负数开方错误"),
MathError::InvalidInput => write!(f, "无效输入"),
}
}
}
impl std::error::Error for MathError {}
fn main() {
println!("⚠️ Result枚举示例");
println!("==================");
// 基本Result使用
let success: Result<i32, &str> = Ok(42);
let failure: Result<i32, &str> = Err("出错了");
println!("成功结果: {:?}", success);
println!("失败结果: {:?}", failure);
// 使用match处理Result
match success {
Ok(value) => println!("成功获得值: {}", value),
Err(error) => println!("错误: {}", error),
}
match failure {
Ok(value) => println!("成功获得值: {}", value),
Err(error) => println!("错误: {}", error),
}
// Result的方法
demonstrate_result_methods();
// 数学运算示例
demonstrate_math_operations();
// 文件操作示例
demonstrate_file_operations();
// 错误传播
demonstrate_error_propagation();
}
fn demonstrate_result_methods() {
println!("\nResult的常用方法:");
let success: Result<i32, &str> = Ok(42);
let failure: Result<i32, &str> = Err("错误");
// is_ok() 和 is_err()
println!("success.is_ok(): {}", success.is_ok());
println!("success.is_err(): {}", success.is_err());
println!("failure.is_ok(): {}", failure.is_ok());
println!("failure.is_err(): {}", failure.is_err());
// unwrap() - 危险!只在确定成功时使用
println!("success.unwrap(): {}", success.unwrap());
// println!("failure.unwrap(): {}", failure.unwrap()); // 会panic!
// unwrap_or() - 提供默认值
println!("success.unwrap_or(0): {}", success.unwrap_or(0));
println!("failure.unwrap_or(0): {}", failure.unwrap_or(0));
// unwrap_or_else() - 使用闭包处理错误
let result = failure.unwrap_or_else(|err| {
println!("处理错误: {}", err);
-1
});
println!("错误处理后的值: {}", result);
// map() - 转换成功值
let doubled = success.map(|x| x * 2);
let doubled_err = failure.map(|x| x * 2);
println!("success.map(|x| x * 2): {:?}", doubled);
println!("failure.map(|x| x * 2): {:?}", doubled_err);
// map_err() - 转换错误值
let mapped_err = failure.map_err(|err| format!("映射的错误: {}", err));
println!("failure.map_err(): {:?}", mapped_err);
// and_then() - 链式操作
let chained = success.and_then(|x| {
if x > 40 {
Ok(x * 2)
} else {
Err("值太小")
}
});
println!("链式操作结果: {:?}", chained);
}
fn demonstrate_math_operations() {
println!("\n数学运算示例:");
// 安全除法
println!("除法运算:");
println!(" 10 / 2 = {:?}", safe_divide(10, 2));
println!(" 10 / 0 = {:?}", safe_divide(10, 0));
// 开方运算
println!("\n开方运算:");
println!(" sqrt(16) = {:?}", safe_sqrt(16.0));
println!(" sqrt(-4) = {:?}", safe_sqrt(-4.0));
// 字符串解析
println!("\n字符串解析:");
println!(" parse('42') = {:?}", parse_positive_number("42"));
println!(" parse('-5') = {:?}", parse_positive_number("-5"));
println!(" parse('abc') = {:?}", parse_positive_number("abc"));
// 复合运算
println!("\n复合运算 (x + y) / z:");
println!(" (10 + 5) / 3 = {:?}", compound_operation(10, 5, 3));
println!(" (10 + 5) / 0 = {:?}", compound_operation(10, 5, 0));
}
fn safe_divide(a: i32, b: i32) -> Result<i32, MathError> {
if b == 0 {
Err(MathError::DivisionByZero)
} else {
Ok(a / b)
}
}
fn safe_sqrt(x: f64) -> Result<f64, MathError> {
if x < 0.0 {
Err(MathError::NegativeSquareRoot)
} else {
Ok(x.sqrt())
}
}
fn parse_positive_number(s: &str) -> Result<i32, MathError> {
let num: i32 = s.parse().map_err(|_| MathError::InvalidInput)?;
if num < 0 {
Err(MathError::InvalidInput)
} else {
Ok(num)
}
}
fn compound_operation(a: i32, b: i32, c: i32) -> Result<i32, MathError> {
let sum = a + b;
safe_divide(sum, c)
}
fn demonstrate_file_operations() {
println!("\n文件操作示例:");
// 尝试读取文件
match read_file_content("example.txt") {
Ok(content) => println!("文件内容: {}", content),
Err(error) => println!("读取文件失败: {}", error),
}
// 创建一个临时文件进行测试
if let Err(e) = std::fs::write("temp.txt", "Hello, Rust!") {
println!("创建临时文件失败: {}", e);
return;
}
match read_file_content("temp.txt") {
Ok(content) => println!("临时文件内容: {}", content.trim()),
Err(error) => println!("读取临时文件失败: {}", error),
}
// 清理临时文件
let _ = std::fs::remove_file("temp.txt");
}
fn read_file_content(filename: &str) -> Result<String, io::Error> {
let mut file = File::open(filename)?;
let mut content = String::new();
file.read_to_string(&mut content)?;
Ok(content)
}
fn demonstrate_error_propagation() {
println!("\n错误传播示例:");
// 使用?操作符传播错误
match process_numbers("10", "5") {
Ok(result) => println!("处理结果: {}", result),
Err(error) => println!("处理失败: {}", error),
}
match process_numbers("10", "0") {
Ok(result) => println!("处理结果: {}", result),
Err(error) => println!("处理失败: {}", error),
}
match process_numbers("abc", "5") {
Ok(result) => println!("处理结果: {}", result),
Err(error) => println!("处理失败: {}", error),
}
// 多步骤操作
println!("\n多步骤操作:");
match multi_step_calculation("100", "10", "2") {
Ok(result) => println!("多步骤计算结果: {}", result),
Err(error) => println!("多步骤计算失败: {}", error),
}
match multi_step_calculation("100", "0", "2") {
Ok(result) => println!("多步骤计算结果: {}", result),
Err(error) => println!("多步骤计算失败: {}", error),
}
}
fn process_numbers(a_str: &str, b_str: &str) -> Result<i32, MathError> {
let a = parse_positive_number(a_str)?;
let b = parse_positive_number(b_str)?;
let result = safe_divide(a, b)?;
Ok(result)
}
fn multi_step_calculation(a_str: &str, b_str: &str, c_str: &str) -> Result<f64, MathError> {
// 解析输入
let a = parse_positive_number(a_str)? as f64;
let b = parse_positive_number(b_str)? as f64;
let c = parse_positive_number(c_str)? as f64;
// 步骤1: a / b
let step1 = if b == 0.0 {
return Err(MathError::DivisionByZero);
} else {
a / b
};
// 步骤2: 开方
let step2 = safe_sqrt(step1)?;
// 步骤3: 乘以c
let result = step2 * c;
Ok(result)
}
rustc result_enum.rs && ./result_enum
5.4 模式匹配
match表达式
#[derive(Debug)]
enum Coin {
Penny,
Nickel,
Dime,
Quarter(UsState),
}
#[derive(Debug)]
enum UsState {
Alabama,
Alaska,
California,
Texas,
}
#[derive(Debug)]
struct Point {
x: i32,
y: i32,
}
#[derive(Debug)]
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(i32, i32, i32),
}
fn main() {
println!("🎯 模式匹配示例");
println!("===============");
// 基本match使用
let coin = Coin::Quarter(UsState::California);
let value = value_in_cents(&coin);
println!("硬币 {:?} 的价值: {} 美分", coin, value);
let coins = vec![
Coin::Penny,
Coin::Nickel,
Coin::Dime,
Coin::Quarter(UsState::Alaska),
Coin::Quarter(UsState::Texas),
];
println!("\n所有硬币的价值:");
for coin in &coins {
println!(" {:?}: {} 美分", coin, value_in_cents(coin));
}
// Option的模式匹配
demonstrate_option_matching();
// 复杂模式匹配
demonstrate_complex_patterns();
// if let 语法
demonstrate_if_let();
// while let 语法
demonstrate_while_let();
}
fn value_in_cents(coin: &Coin) -> u8 {
match coin {
Coin::Penny => {
println!("幸运便士!");
1
}
Coin::Nickel => 5,
Coin::Dime => 10,
Coin::Quarter(state) => {
println!("来自 {:?} 州的25美分硬币!", state);
25
}
}
}
fn demonstrate_option_matching() {
println!("\nOption模式匹配:");
let numbers = vec![Some(1), None, Some(3), Some(4), None, Some(6)];
for (i, number) in numbers.iter().enumerate() {
match number {
Some(value) => println!(" 位置{}: 有值 {}", i, value),
None => println!(" 位置{}: 无值", i),
}
}
// 使用match进行计算
let sum = numbers.iter().fold(0, |acc, &opt| {
match opt {
Some(value) => acc + value,
None => acc,
}
});
println!("所有Some值的和: {}", sum);
// 匹配范围
let number = 13;
match number {
1..=5 => println!("{} 在1到5之间", number),
6..=10 => println!("{} 在6到10之间", number),
11..=15 => println!("{} 在11到15之间", number),
_ => println!("{} 在其他范围", number),
}
}
fn demonstrate_complex_patterns() {
println!("\n复杂模式匹配:");
// 结构体模式匹配
let points = vec![
Point { x: 0, y: 0 },
Point { x: 1, y: 5 },
Point { x: 10, y: -3 },
];
for point in &points {
match point {
Point { x: 0, y: 0 } => println!("原点"),
Point { x: 0, y } => println!("在Y轴上,y = {}", y),
Point { x, y: 0 } => println!("在X轴上,x = {}", x),
Point { x, y } => println!("其他点 ({}, {})", x, y),
}
}
// 枚举模式匹配
let messages = vec![
Message::Quit,
Message::Move { x: 10, y: 20 },
Message::Write(String::from("Hello")),
Message::ChangeColor(255, 0, 0),
];
for message in &messages {
match message {
Message::Quit => println!("退出消息"),
Message::Move { x, y } => {
println!("移动到 ({}, {})", x, y);
}
Message::Write(text) => {
println!("写入文本: {}", text);
}
Message::ChangeColor(r, g, b) => {
println!("改变颜色为 RGB({}, {}, {})", r, g, b);
}
}
}
// 守卫条件
let number = Some(4);
match number {
Some(x) if x < 5 => println!("小于5的数: {}", x),
Some(x) => println!("大于等于5的数: {}", x),
None => println!("没有数"),
}
// 多个模式
let x = 1;
match x {
1 | 2 => println!("一或二"),
3 => println!("三"),
_ => println!("其他"),
}
// 解构元组
let tuple = (1, 2, 3);
match tuple {
(0, y, z) => println!("第一个是0,y = {}, z = {}", y, z),
(1, ..) => println!("第一个是1,忽略其余"),
(.., 3) => println!("最后一个是3,忽略其余"),
(x, y, z) => println!("({}, {}, {})", x, y, z),
}
}
fn demonstrate_if_let() {
println!("\nif let 语法:");
let some_value = Some(3);
// 使用match
match some_value {
Some(3) => println!("三"),
_ => (),
}
// 使用if let(更简洁)
if let Some(3) = some_value {
println!("三(使用if let)");
}
// 更复杂的if let
let coin = Coin::Quarter(UsState::California);
if let Coin::Quarter(state) = coin {
println!("来自 {:?} 州的25美分硬币!", state);
} else {
println!("不是25美分硬币");
}
// if let with else
let number = Some(7);
if let Some(x) = number {
println!("数字是: {}", x);
} else {
println!("没有数字");
}
// 多个if let
let values = vec![Some(1), None, Some(3), Some(4)];
for value in values {
if let Some(x) = value {
if x > 2 {
println!("大于2的值: {}", x);
}
}
}
}
fn demonstrate_while_let() {
println!("\nwhile let 语法:");
let mut stack = Vec::new();
stack.push(1);
stack.push(2);
stack.push(3);
println!("栈内容: {:?}", stack);
// 使用while let弹出所有元素
while let Some(top) = stack.pop() {
println!("弹出: {}", top);
}
println!("栈现在为空: {:?}", stack);
// 处理迭代器
let numbers = vec![1, 2, 3, 4, 5];
let mut iter = numbers.iter();
while let Some(num) = iter.next() {
if *num > 3 {
println!("找到大于3的数: {}", num);
break;
}
}
}
rustc pattern_matching.rs && ./pattern_matching
5.5 综合示例:任务管理系统
use std::collections::HashMap;
use std::fmt;
#[derive(Debug, Clone, PartialEq)]
enum Priority {
Low,
Medium,
High,
Urgent,
}
impl fmt::Display for Priority {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Priority::Low => write!(f, "低"),
Priority::Medium => write!(f, "中"),
Priority::High => write!(f, "高"),
Priority::Urgent => write!(f, "紧急"),
}
}
}
#[derive(Debug, Clone, PartialEq)]
enum Status {
Todo,
InProgress,
Done,
Cancelled,
}
impl fmt::Display for Status {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Status::Todo => write!(f, "待办"),
Status::InProgress => write!(f, "进行中"),
Status::Done => write!(f, "已完成"),
Status::Cancelled => write!(f, "已取消"),
}
}
}
#[derive(Debug, Clone)]
struct Task {
id: u32,
title: String,
description: String,
priority: Priority,
status: Status,
assignee: Option<String>,
}
impl Task {
fn new(id: u32, title: String, description: String) -> Self {
Task {
id,
title,
description,
priority: Priority::Medium,
status: Status::Todo,
assignee: None,
}
}
fn set_priority(&mut self, priority: Priority) {
self.priority = priority;
}
fn set_status(&mut self, status: Status) {
self.status = status;
}
fn assign_to(&mut self, assignee: String) {
self.assignee = Some(assignee);
}
fn unassign(&mut self) {
self.assignee = None;
}
fn is_completed(&self) -> bool {
matches!(self.status, Status::Done)
}
fn is_active(&self) -> bool {
matches!(self.status, Status::Todo | Status::InProgress)
}
}
impl fmt::Display for Task {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[{}] {} - {} ({})",
self.id, self.title, self.status, self.priority)?;
if let Some(ref assignee) = self.assignee {
write!(f, " -> {}", assignee)?;
}
Ok(())
}
}
struct TaskManager {
tasks: HashMap<u32, Task>,
next_id: u32,
}
impl TaskManager {
fn new() -> Self {
TaskManager {
tasks: HashMap::new(),
next_id: 1,
}
}
fn add_task(&mut self, title: String, description: String) -> u32 {
let id = self.next_id;
let task = Task::new(id, title, description);
self.tasks.insert(id, task);
self.next_id += 1;
id
}
fn get_task(&self, id: u32) -> Option<&Task> {
self.tasks.get(&id)
}
fn get_task_mut(&mut self, id: u32) -> Option<&mut Task> {
self.tasks.get_mut(&id)
}
fn remove_task(&mut self, id: u32) -> Option<Task> {
self.tasks.remove(&id)
}
fn list_tasks(&self) -> Vec<&Task> {
self.tasks.values().collect()
}
fn list_tasks_by_status(&self, status: Status) -> Vec<&Task> {
self.tasks.values()
.filter(|task| task.status == status)
.collect()
}
fn list_tasks_by_priority(&self, priority: Priority) -> Vec<&Task> {
self.tasks.values()
.filter(|task| task.priority == priority)
.collect()
}
fn list_tasks_by_assignee(&self, assignee: &str) -> Vec<&Task> {
self.tasks.values()
.filter(|task| {
if let Some(ref task_assignee) = task.assignee {
task_assignee == assignee
} else {
false
}
})
.collect()
}
fn get_statistics(&self) -> TaskStatistics {
let mut stats = TaskStatistics::new();
for task in self.tasks.values() {
stats.total += 1;
match task.status {
Status::Todo => stats.todo += 1,
Status::InProgress => stats.in_progress += 1,
Status::Done => stats.done += 1,
Status::Cancelled => stats.cancelled += 1,
}
match task.priority {
Priority::Low => stats.low_priority += 1,
Priority::Medium => stats.medium_priority += 1,
Priority::High => stats.high_priority += 1,
Priority::Urgent => stats.urgent_priority += 1,
}
}
stats
}
}
#[derive(Debug)]
struct TaskStatistics {
total: usize,
todo: usize,
in_progress: usize,
done: usize,
cancelled: usize,
low_priority: usize,
medium_priority: usize,
high_priority: usize,
urgent_priority: usize,
}
impl TaskStatistics {
fn new() -> Self {
TaskStatistics {
total: 0,
todo: 0,
in_progress: 0,
done: 0,
cancelled: 0,
low_priority: 0,
medium_priority: 0,
high_priority: 0,
urgent_priority: 0,
}
}
fn completion_rate(&self) -> f64 {
if self.total == 0 {
0.0
} else {
(self.done as f64 / self.total as f64) * 100.0
}
}
}
impl fmt::Display for TaskStatistics {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln!(f, "任务统计:")?;
writeln!(f, " 总任务数: {}", self.total)?;
writeln!(f, " 状态分布:")?;
writeln!(f, " 待办: {}", self.todo)?;
writeln!(f, " 进行中: {}", self.in_progress)?;
writeln!(f, " 已完成: {}", self.done)?;
writeln!(f, " 已取消: {}", self.cancelled)?;
writeln!(f, " 优先级分布:")?;
writeln!(f, " 低: {}", self.low_priority)?;
writeln!(f, " 中: {}", self.medium_priority)?;
writeln!(f, " 高: {}", self.high_priority)?;
writeln!(f, " 紧急: {}", self.urgent_priority)?;
write!(f, " 完成率: {:.1}%", self.completion_rate())
}
}
fn main() {
println!("📋 任务管理系统示例");
println!("====================");
let mut manager = TaskManager::new();
// 添加任务
let task1_id = manager.add_task(
"学习Rust".to_string(),
"完成Rust语言基础教程".to_string()
);
let task2_id = manager.add_task(
"写项目文档".to_string(),
"为新项目编写技术文档".to_string()
);
let task3_id = manager.add_task(
"代码审查".to_string(),
"审查团队成员的代码提交".to_string()
);
let task4_id = manager.add_task(
"修复Bug".to_string(),
"修复生产环境中的紧急Bug".to_string()
);
// 设置任务属性
if let Some(task) = manager.get_task_mut(task1_id) {
task.set_priority(Priority::High);
task.assign_to("Alice".to_string());
task.set_status(Status::InProgress);
}
if let Some(task) = manager.get_task_mut(task2_id) {
task.set_priority(Priority::Medium);
task.assign_to("Bob".to_string());
}
if let Some(task) = manager.get_task_mut(task3_id) {
task.set_priority(Priority::Low);
task.assign_to("Charlie".to_string());
task.set_status(Status::Done);
}
if let Some(task) = manager.get_task_mut(task4_id) {
task.set_priority(Priority::Urgent);
task.assign_to("Alice".to_string());
}
// 显示所有任务
println!("所有任务:");
for task in manager.list_tasks() {
println!(" {}", task);
println!(" 描述: {}", task.description);
}
// 按状态筛选
println!("\n待办任务:");
for task in manager.list_tasks_by_status(Status::Todo) {
println!(" {}", task);
}
println!("\n进行中的任务:");
for task in manager.list_tasks_by_status(Status::InProgress) {
println!(" {}", task);
}
// 按优先级筛选
println!("\n紧急任务:");
for task in manager.list_tasks_by_priority(Priority::Urgent) {
println!(" {}", task);
}
// 按负责人筛选
println!("\nAlice的任务:");
for task in manager.list_tasks_by_assignee("Alice") {
println!(" {}", task);
}
// 显示统计信息
println!("\n{}", manager.get_statistics());
// 任务操作演示
demonstrate_task_operations(&mut manager);
}
fn demonstrate_task_operations(manager: &mut TaskManager) {
println!("\n任务操作演示:");
// 完成一个任务
if let Some(task) = manager.get_task_mut(1) {
task.set_status(Status::Done);
println!("任务1已完成: {}", task);
}
// 取消一个任务
let new_task_id = manager.add_task(
"临时任务".to_string(),
"这是一个临时任务".to_string()
);
if let Some(task) = manager.get_task_mut(new_task_id) {
task.set_status(Status::Cancelled);
println!("任务{}已取消: {}", new_task_id, task);
}
// 重新分配任务
if let Some(task) = manager.get_task_mut(2) {
task.unassign();
task.assign_to("David".to_string());
println!("任务2重新分配: {}", task);
}
// 更新后的统计信息
println!("\n更新后的统计信息:");
println!("{}", manager.get_statistics());
// 查找特定任务
match manager.get_task(1) {
Some(task) => {
println!("\n找到任务1:");
println!(" {}", task);
println!(" 是否完成: {}", task.is_completed());
println!(" 是否活跃: {}", task.is_active());
}
None => println!("任务1不存在"),
}
// 删除任务
if let Some(removed_task) = manager.remove_task(new_task_id) {
println!("\n删除了任务: {}", removed_task);
}
println!("\n最终任务列表:");
for task in manager.list_tasks() {
println!(" {}", task);
}
}
rustc task_manager.rs && ./task_manager
本章小结
通过本章学习,你应该掌握了:
✅ 结构体定义: 普通结构体、元组结构体、单元结构体 ✅ 方法和关联函数: impl块、self参数、静态方法 ✅ 枚举类型: 基本枚举、带数据的枚举、方法实现 ✅ Option和Result: 处理可能为空的值和错误 ✅ 模式匹配: match表达式、if let、while let ✅ 复杂数据结构: 组合使用结构体和枚举
下一章预告
在下一章《控制流》中,我们将学习:
- 条件语句和循环
- 迭代器和闭包
- 错误处理模式
- 函数式编程概念
- 高级控制流技巧
练习题
练习1:图书管理系统
设计一个图书管理系统,包含图书、作者、借阅记录等结构体和相关枚举。
练习2:计算器
实现一个支持四则运算的计算器,使用枚举表示操作类型。
练习3:学生成绩管理
创建学生和课程的数据结构,实现成绩录入和统计功能。
练习4:简单状态机
使用枚举实现一个简单的状态机,如交通灯控制系统。
恭喜你掌握了Rust的数据结构! 🎉
结构体和枚举是Rust中组织数据的核心工具,配合模式匹配,可以构建出既安全又表达力强的程序。现在让我们继续学习控制流!