← [ BACK_TO_NOTES ]

Rust 泛型

类型参数如何抽象函数与结构体;trait bound 约束;单态化与成本边界。

#concept #growing #dev #rust

[!info] related notes

Rust 泛型

这个概念为什么出现

不想为 i32/String/UserId 各写一遍相同算法。
泛型把“类型”参数化,再配合 trait bound 限制“必须具备的能力”。

[!abstract] 一句话理解 泛型是类型参数;T: Trait 限制可用操作;编译器通常通过单态化为每个具体类型生成专用代码,换运行时效率。

最小可运行示例

场景:库存服务——在任意可比较的 ID 列表中找最大值

SKU 数、仓库优先级等都要“找最大”;元素只需 Ord。

// 业务意图:找最大元素;空切片返回 None。
// 教学点:泛型函数 + Ord bound;返回引用避免 move。

fn max_in<T: Ord>(items: &[T]) -> Option<&T> {
    let mut best = items.first()?;
    for item in items.iter().skip(1) {
        if item > best {
            best = item;
        }
    }
    Some(best)
}

fn main() {
    let stock = [3, 9, 4, 9, 1];
    println!("max_stock={}", max_in(&stock).unwrap());
    let names = ["sku-b", "sku-a", "sku-c"];
    println!("max_name={}", max_in(&names).unwrap());
}

建议运行:cargo run

期望输出:

max_stock=9
max_name=sku-c

空切片返回 None;最大值相等时保留首个出现的元素引用。f32/f64 没有 Ord(NaN 无法按普通比较建立全序),需先定义排序政策,不能直接套此约束。

结合场景再看三个关注点

  1. 同一函数服务多类型
  2. 返回 &T 不搬出所有权
  3. Ord bound 让 > 合法

核心概念与准确模型

泛型结构体/枚举

struct Wrapper<T> { value: T }
enum Maybe<T> { Some(T), None }

约束与 where

fn print_it<T>(x: T) where T: std::fmt::Display {
    println!("{x}");
}

单态化

编译器为 max_in::<i32> 与 max_in::<&str> 生成不同版本(概念模型)。
代价是编译时间和代码体积可能增加;收益是可静态分发与内联。优化器可以合并或内联实例,最终机器码不保证每种类型都有独立函数符号。

与生命周期参数

<'a, T> 可同时出现,见 生命周期。

设计动机

  • 抽象而不放弃类型安全
  • 抽象不必引入运行时虚调用,但不意味着编译、代码体积与实际运行成本都为零
  • 标准库大量建立在泛型上(Option/Result/Vec)

边界与误区

  • 过度泛型损害可读性
  • 推断失败时补注解
  • 泛型方法与 trait 对象对象安全互相牵扯

[!warning] 常见误区:无 bound 却对 T 调用方法 编译器不知道 T 有哪些方法;加 trait bound。

工程实践

  1. 先写具体类型,再抽取泛型
  2. bound 尽量小
  3. 公共 API 稳定后谨慎增加参数
  4. 性能敏感处对比 dyn 与泛型

本节总结

  • 类型参数 + bound
  • 单态化是默认实现策略教学模型
  • 与 trait 一体

自测题

  1. 为什么 fn id<T>(x: T) -> T { x } 不需要 bound?
  2. 单态化的主要代价是什么?
参考答案
  1. 只移动值,不调用 T 的方法。
  2. 可能的代码膨胀与编译时间。

延伸阅读与资料来源

资料类型支撑内容
The Book — Generic Types官方书泛型
The Book — Performance of Monomorphization官方书相关讨论
创建于 2026/7/15 更新于 2026/10/7
Digital Biome
Access

键盘导航

j / k / ↑ / ↓
选择对象
Enter / o
打开选择
/ 或 Ctrl+K
全站搜索
i / f / 1–4
筛选当前列表
g → h / l / p / t / a
首页 / 笔记 / 项目 / 工具 / About
r → 1–9
打开所选对象的关联
u
返回上一页
Esc
关闭浮层 / 取消命令;输入框内清空文本