【Rust】结构体(Struct)详解

结构体(struct)是 Rust 中自定义复合数据类型的主要方式,允许你将多个相关值组合在一起。

1. 基本结构体定义

定义和实例化

rust 复制代码
// 定义结构体
struct User {
    username: String,
    email: String,
    sign_in_count: u64,
    active: bool,
}

// 创建实例
let user1 = User {
    email: String::from("someone@example.com"),
    username: String::from("someusername123"),
    active: true,
    sign_in_count: 1,
};

// 访问字段
println!("用户名: {}", user1.username);
println!("邮箱: {}", user1.email);

可变结构体

rust 复制代码
let mut user1 = User {
    email: String::from("someone@example.com"),
    username: String::from("someusername123"),
    active: true,
    sign_in_count: 1,
};

// 修改字段值
user1.email = String::from("anotheremail@example.com");
user1.sign_in_count += 1;

2. 结构体更新语法

rust 复制代码
let user1 = User {
    email: String::from("user1@example.com"),
    username: String::from("user1"),
    active: true,
    sign_in_count: 1,
};

// 使用更新语法创建新实例
let user2 = User {
    email: String::from("user2@example.com"),
    username: String::from("user2"),
    ..user1  // 继承 user1 的其他字段
};

// user2 将拥有 user1 的 active 和 sign_in_count 值

3. 元组结构体

没有字段名,只有类型的结构体:

rust 复制代码
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);

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

// 通过索引访问
println!("红色分量: {}", black.0);
println!("x坐标: {}", origin.0);

// 即使字段类型相同,也是不同的类型
// let color: Color = origin; // 错误!类型不匹配

4. 类单元结构体

没有字段的结构体:

rust 复制代码
struct AlwaysEqual;

let subject = AlwaysEqual;

// 常用于 trait 实现或标记类型
impl AlwaysEqual {
    fn new() -> Self {
        AlwaysEqual
    }
}

5. 结构体方法

定义方法

rust 复制代码
struct Rectangle {
    width: u32,
    height: u32,
}

// 使用 impl 块定义方法
impl Rectangle {
    // 关联函数(类似静态方法)
    fn new(width: u32, height: u32) -> Self {
        Rectangle { width, height }
    }
    
    // 实例方法
    fn area(&self) -> u32 {
        self.width * self.height
    }
    
    fn can_hold(&self, other: &Rectangle) -> bool {
        self.width > other.width && self.height > other.height
    }
    
    // 修改方法
    fn scale(&mut self, factor: f32) {
        self.width = (self.width as f32 * factor) as u32;
        self.height = (self.height as f32 * factor) as u32;
    }
    
    // 获取器(getter)
    fn width(&self) -> u32 {
        self.width
    }
    
    fn height(&self) -> u32 {
        self.height
    }
}

// 使用
let rect = Rectangle::new(30, 50);
println!("面积: {}", rect.area());

let mut rect2 = Rectangle::new(10, 20);
rect2.scale(1.5);

多个 impl 块

rust 复制代码
impl Rectangle {
    fn square(size: u32) -> Self {
        Rectangle { width: size, height: size }
    }
}

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

6. 关联函数 vs 方法

rust 复制代码
struct Circle {
    radius: f64,
}

impl Circle {
    // 关联函数 - 没有 self 参数
    fn new(radius: f64) -> Self {
        Circle { radius }
    }
    
    // 方法 - 有 self 参数
    fn area(&self) -> f64 {
        std::f64::consts::PI * self.radius * self.radius
    }
}

// 使用
let circle = Circle::new(5.0);  // 调用关联函数
let area = circle.area();       // 调用方法

7. 结构体与所有权

使用引用字段

rust 复制代码
struct User<'a> {
    username: &'a str,      // 字符串切片引用
    email: &'a str,
    sign_in_count: u64,
}

let username = "john_doe";
let email = "john@example.com";
let user = User {
    username,
    email,
    sign_in_count: 1,
};

使用 String(拥有所有权)

rust 复制代码
struct OwnedUser {
    username: String,      // 拥有字符串所有权
    email: String,
    sign_in_count: u64,
}

8. Debug 打印

rust 复制代码
#[derive(Debug)]  // 自动实现 Debug trait
struct Point {
    x: i32,
    y: i32,
}

let point = Point { x: 10, y: 20 };
println!("{:?}", point);     // 调试输出: Point { x: 10, y: 20 }
println!("{:#?}", point);    // 美化输出
// Point {
//     x: 10,
//     y: 20,
// }

9. 结构体模式匹配

rust 复制代码
struct Point {
    x: i32,
    y: i32,
}

let point = Point { x: 10, y: 20 };

// 解构结构体
let Point { x, y } = point;
println!("x: {}, y: {}", x, y);

// 模式匹配
match point {
    Point { x: 0, y: 0 } => println!("原点"),
    Point { x, y: 0 } => println!("x轴上的点: {}", x),
    Point { x: 0, y } => println!("y轴上的点: {}", y),
    Point { x, y } => println!("点({}, {})", x, y),
}

10. 常用 trait 派生

rust 复制代码
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
struct Point {
    x: i32,
    y: i32,
}

#[derive(Debug, Default)]
struct Config {
    timeout: u32,
    retries: u32,
}

// 使用默认值
let config = Config::default();  // timeout: 0, retries: 0

11. 泛型结构体

rust 复制代码
// 泛型结构体
struct Pair<T, U> {
    first: T,
    second: U,
}

// 使用
let integer_pair = Pair { first: 5, second: 10 };
let mixed_pair = Pair { first: "hello", second: 42.5 };

// 泛型方法实现
impl<T, U> Pair<T, U> {
    fn new(first: T, second: U) -> Self {
        Pair { first, second }
    }
    
    fn swap(self) -> Pair<U, T> {
        Pair {
            first: self.second,
            second: self.first,
        }
    }
}

12. Newtype 模式

使用元组结构体创建新类型:

rust 复制代码
struct Kilometers(i32);
struct Meters(i32);

let distance1 = Kilometers(5);
let distance2 = Meters(5000);

// 这样不会意外混淆不同类型
// let total = distance1 + distance2; // 编译错误!

13. 结构体最佳实践

  1. 命名规范:使用大驼峰命名法
  2. 字段访问:考虑提供 getter/setter
  3. 不可变性:优先使用不可变结构体
  4. 所有权:根据需求选择引用或拥有所有权
  5. 文档注释:为公共结构体添加文档
rust 复制代码
/// 表示一个二维点
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Point {
    /// x 坐标
    pub x: f64,
    /// y 坐标
    pub y: f64,
}

impl Point {
    /// 创建新点
    pub fn new(x: f64, y: f64) -> Self {
        Point { x, y }
    }
    
    /// 计算到原点的距离
    pub fn distance_from_origin(&self) -> f64 {
        (self.x * self.x + self.y * self.y).sqrt()
    }
}

14. 结构体 vs 枚举 vs 元组

特性 结构体 枚举 元组
字段名
变体 有多个
访问 点号 模式匹配 索引
用途 数据聚合 选择分支 简单组合

总结

Rust 结构体提供了:

  • 数据封装:将相关数据组合在一起
  • 类型安全:编译时检查字段访问
  • 方法封装:将数据与操作绑定
  • 灵活性:支持泛型、生命周期等
  • 模式匹配:强大的解构能力

结构体是 Rust 面向数据编程的核心,结合枚举和 trait,构成了 Rust 强大的类型系统。

复制代码
相关推荐
isyuah7 小时前
Miko v0.7 发布:我写的一个 Rust Web 框架,虽然还是个玩具
后端·rust
isyuah7 小时前
Miko 框架系列(十四):集成测试
后端·rust
唐装鼠8 小时前
Rust Turbofish 语法详解(deepseek)
开发语言·后端·rust
Source.Liu8 小时前
【Rust】字符串类型全览:从 UTF-8 到系统路径
rust
唐装鼠8 小时前
Rust 中的 `parse` 方法详解(deepseek)
开发语言·后端·rust
唐装鼠8 小时前
Rust 自动引用规则完全指南(deepseek)
开发语言·后端·rust
唐装鼠8 小时前
Rust Borrow 和 BorrowMut(deepseek)
rust
唐装鼠19 小时前
rust自动调用Deref(deepseek)
开发语言·算法·rust
jump_jump19 小时前
手写一个 Askama 模板压缩工具
前端·性能优化·rust