1. 为什么要用泛型
- 用同一套逻辑处理不同类型数据,避免为每种类型重复写函数
- 减少冗余代码,提升表达能力,是一种多态实现
无泛型(啰嗦版)
rust
fn add_i8(a:i8, b:i8) -> i8 { a + b }
fn add_i32(a:i32, b:i32) -> i32 { a + b }
fn add_f64(a:f64, b:f64) -> f64 { a + b }
泛型版(简洁但不能直接编译,需约束)
rust
fn add<T>(a:T, b:T) -> T {
a + b
}
2. 泛型基础语法
T是泛型参数名(惯例用 T=Type)- 使用前必须先声明 :
<T>·
- 使用前必须先声明 :
rust
fn largest<T>(list: &[T]) -> T { ... }
3. 关键:泛型约束(Trait Bound)
不是所有类型都支持比较、加减,必须用 Trait 限制 T 的行为。
① 比较约束(取最大值)
rust
fn largest<T: PartialOrd>(list: &[T]) -> &T {
let mut largest = &list[0];
for item in list {
if item > largest {
largest = item;
}
}
largest
}
② 加法约束
rust
fn add<T: std::ops::Add<Output = T>>(a:T, b:T) -> T {
a + b
}
4. 显式指定泛型类型
编译器无法自动推断时,用 ::<类型> 手动指定:
rust
use std::fmt::Display;
fn create_and_print<T>() where T: From<i32> + Display {
let a: T = 100.into();
println!("a is: {}", a);
}
fn main() {
create_and_print::<i64>(); // 显式指定 T=i64
}
5. 结构体泛型
单泛型(同类型字段)
rust
struct Point<T> {
x: T,
y: T,
}
// x、y 必须同类型
let p = Point { x: 1, y: 2 };
多泛型(不同类型字段)
rust
struct Point<T, U> {
x: T,
y: U,
}
// x 整数,y 浮点,正常使用
let p = Point { x: 1, y: 1.1 };
6. 枚举泛型(标准库核心)
Option
rust
enum Option<T> {
Some(T),
None,
}
Result<T, E>(错误处理)
rust
enum Result<T, E> {
Ok(T),
Err(E),
}
7. 方法中的泛型
为泛型结构体实现方法
rust
struct Point<T> { x: T, y: T }
impl<T> Point<T> { // 先声明泛型 T
fn x(&self) -> &T {
&self.x
}
}
方法自带额外泛型
rust
impl<T, U> Point<T, U> {
// V、W 是方法自己的泛型
fn mixup<V, W>(self, other: Point<V, W>) -> Point<T, W> {
Point { x: self.x, y: other.y }
}
}
为具体类型实现方法
rust
// 只有 f32 类型的 Point 才有此方法
impl Point<f32> {
fn distance_from_origin(&self) -> f32 {
(self.x.powi(2) + self.y.powi(2)).sqrt()
}
}
8. Rust 特色:const 泛型(针对值的泛型)
解决不同长度数组是不同类型 的问题,const N: usize 代表数组长度。
rust
// T=类型泛型,N=值泛型(数组长度)
fn display_array<T: std::fmt::Debug, const N: usize>(arr: [T; N]) {
println!("{:?}", arr);
}
fn main() {
display_array([1,2,3]);
display_array([1,2]); // 长度不同也可通用
}
9. const fn(编译期执行函数)
允许在编译期计算,常用于配合 const 泛型设置数组 / 缓冲区长度。
rust
const fn add(a: usize, b: usize) -> usize {
a + b
}
const RESULT: usize = add(5, 10); // 编译期算出结果
const fn + const 泛型
rust
struct Buffer<const N: usize> {
data: [u8; N],
}
const fn size(f: usize) -> usize { f * 1024 }
fn main() {
const S: usize = size(4);
let buf = Buffer::<S> { data: [0; S] };
}
10. 泛型性能:零成本抽象
- Rust 在编译期做单态化:为每种实际类型生成独立代码
- 运行时无额外开销,效率等同于手写多份重复代码
- 代价:编译稍慢、二进制体积稍大
示例:
rust
let integer = Some(5);
let float = Some(5.0);
编译后会生成:
rust
enum Option_i32 { Some(i32), None }
enum Option_f64 { Some(f64), None }
全文核心要点
- 泛型 = 通用代码模板,减少重复
- 泛型必须先声明再使用
- 必须用 Trait 约束类型行为(比较、加法等)
- 支持函数、结构体、枚举、方法泛型
- Rust 独有:const 泛型 (处理长度 / 常量)+ const fn(编译期计算)
- 零成本抽象,运行时无性能损失