Rust 中的泛型:初学者指南——为什么需要以及如何使用

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言:什么是泛型,为什么 Rust 需要它们?

\n

想象一下,你需要编写一个函数来查找列表中的最大元素。对于整数,你需要一个函数;对于浮点数,你需要另一个函数;对于字符串,你还需要第三个函数。代码会重复,维护起来也会变得困难。在 Rust 中,泛型(泛型编程)解决了这个问题。

\n

泛型允许你编写能够处理不同数据类型的代码,同时不丢失严格的类型检查。你不必为每个类型重复编写函数,而是编写一个通用版本。Rust 在编译时会替换具体的类型并检查正确性。这带来了以下好处:

\n
    \n
  • 代码复用 —— 一个函数适用于所有类型。
  • \n
  • 安全性 —— 所有类型错误都在编译时被捕获。
  • \n
  • 性能 —— 得益于单态化(编译器为每个使用的类型生成单独的代码),泛型代码的运行速度与专用代码一样快。
  • \n
\n

在本文中,我们将通过实际示例,从简单的函数到结构体和 trait,讲解如何在 Rust 中使用泛型。

\n\n

1. 函数中的泛型:迈向通用性的第一步

\n

语法和基本示例

\n

要使函数成为泛型,你需要在尖括号 <T> 中指定一个类型参数。通常使用大写字母:T、U、V。下面是一个返回传入值的函数:

\n
fn identity<T>(value: T) -> T {\n    value\n}\n\nfn main() {\n    let num = identity(42);\n    let text = identity("Hello");\n    println!("{} {}", num, text); // 输出:42 Hello\n}
\n

编译器会根据传入的参数自动推断类型。你也可以显式指定类型:identity::<i32>(42)。

\n\n

约束:作为类型边界的 trait

\n

如果我们想比较值呢?直接写 value1 > value2 是不行的——并非所有类型都支持比较。你需要指定该类型必须实现 PartialOrd trait:

\n
fn largest<T: PartialOrd>(list: &[T]) -> &T {\n    let mut largest = &list[0];\n    for item in list {\n        if item > largest {\n            largest = item;\n        }\n    }\n    largest\n}\n\nfn main() {\n    let numbers = vec![34, 50, 25, 100, 65];\n    println!("最大数字:{}", largest(&numbers));\n\n    let chars = vec!['y', 'm', 'a', 'q'];\n    println!("最大字符:{}", largest(&chars));\n}
\n

这里的 T: PartialOrd 是一个 trait 约束。它保证了类型 T 定义了比较运算符。如果没有这个约束,代码将无法编译。

\n\n

2. 结构体和枚举中的泛型

\n

具有泛型字段的结构体

\n

泛型也适用于自定义类型。例如,Point 结构体可以存储任何类型的坐标:

\n
struct Point<T> {\n    x: T,\n    y: T,\n}\n\nfn main() {\n    let integer_point = Point { x: 5, y: 10 };\n    let float_point = Point { x: 1.0, y: 4.0 };\n    // let mixed = Point { x: 5, y: 4.0 }; // 错误!两个字段必须是同一类型\n}
\n

如果你希望字段可以是不同的类型,请使用多个参数:

\n
struct Point<T, U> {\n    x: T,\n    y: U,\n}\n\nfn main() {\n    let mixed = Point { x: 5, y: 4.0 }; // 现在可以工作了\n}
\n\n

具有泛型的枚举

\n

标准枚举 Option<T> 是泛型枚举的一个很好的例子。你也可以创建自己的枚举:

\n
enum Result<T, E> {\n    Ok(T),\n    Err(E),\n}\n\n// 使用\nfn divide(a: f64, b: f64) -> Result<f64, String> {\n    if b                

博客

书籍推荐