【Rust】09-泛型、Trait 与生命周期基础

泛型、Trait 与生命周期基础

学习目标

  • 理解泛型如何减少重复代码。
  • 使用 trait 表达共享行为。
  • 建立生命周期的基本直觉。

泛型

泛型允许函数、结构体或枚举处理多种类型:

rust 复制代码
fn first<T>(items: &[T]) -> Option<&T> {
    items.first()
}

fn main() {
    let numbers = vec![1, 2, 3];
    let names = vec!["Alice", "Bob"];

    println!("{:?}", first(&numbers));
    println!("{:?}", first(&names));
}

T 是类型参数。它表示"某个具体类型",编译器会在使用时推断出来。

泛型结构体

rust 复制代码
struct Point<T> {
    x: T,
    y: T,
}

fn main() {
    let integer = Point { x: 1, y: 2 };
    let float = Point { x: 1.0, y: 2.0 };

    println!("{}, {}", integer.x, float.x);
}

如果两个字段允许不同类型,可以使用两个类型参数:

rust 复制代码
struct Pair<T, U> {
    left: T,
    right: U,
}

Trait

Trait 定义共享行为,类似"能力约束":

rust 复制代码
trait Summary {
    fn summarize(&self) -> String;
}

struct Article {
    title: String,
    author: String,
}

impl Summary for Article {
    fn summarize(&self) -> String {
        format!("{} by {}", self.title, self.author)
    }
}

使用 trait 约束函数参数:

rust 复制代码
fn print_summary(item: &impl Summary) {
    println!("{}", item.summarize());
}

这表示参数可以是任何实现了 Summary 的类型。

Trait Bound

更完整的泛型写法:

rust 复制代码
fn print_summary<T: Summary>(item: &T) {
    println!("{}", item.summarize());
}

多个约束可以用 +

rust 复制代码
use std::fmt::Debug;

fn inspect<T: Summary + Debug>(item: &T) {
    println!("{item:?}");
    println!("{}", item.summarize());
}

复杂约束可以用 where

rust 复制代码
fn compare_and_print<T, U>(left: &T, right: &U)
where
    T: Summary + Clone,
    U: Summary + std::fmt::Debug,
{
    println!("{}", left.summarize());
    println!("{right:?}");
}

默认实现

Trait 可以提供默认方法:

rust 复制代码
trait Summary {
    fn author(&self) -> &str;

    fn summarize(&self) -> String {
        format!("article by {}", self.author())
    }
}

实现者只需要提供没有默认实现的方法。

生命周期要解决什么

生命周期描述引用之间的有效范围关系。它不会延长任何值的生命,只是让编译器确认引用不会悬垂。

很多时候生命周期可以省略:

rust 复制代码
fn first_word(text: &str) -> &str {
    text.split_whitespace().next().unwrap_or("")
}

编译器能推断返回值来自参数 text

当有多个输入引用,返回值来源不明显时,需要标注:

rust 复制代码
fn longest<'a>(left: &'a str, right: &'a str) -> &'a str {
    if left.len() >= right.len() {
        left
    } else {
        right
    }
}

'a 表示返回引用的有效期不能超过 leftright 中较短的那个。

结构体中的引用

如果结构体存储引用,需要生命周期参数:

rust 复制代码
struct Excerpt<'a> {
    part: &'a str,
}

fn main() {
    let text = String::from("Rust is fast and safe.");
    let first = text.split('.').next().unwrap_or("");
    let excerpt = Excerpt { part: first };

    println!("{}", excerpt.part);
}

这表示 Excerpt 不能比它引用的字符串片段活得更久。

常见误区

  • 泛型不是运行时动态类型;Rust 通常会在编译期为具体类型生成代码。
  • Trait 是行为抽象,不只是接口语法。
  • 生命周期标注不会改变对象实际存活时间。
  • 遇到生命周期错误时,先检查谁拥有数据、谁借用了数据、返回引用来自哪里。

练习

  1. 写一个泛型函数,返回切片的最后一个元素。
  2. 定义一个 DisplayName trait,并为两个结构体实现它。
  3. 写一个函数,在两个 &str 中返回更短的那个,并添加必要生命周期标注。

后记

2026年6月10日17点42分于上海。

相关推荐
独孤留白12 小时前
从C到Rust:Rust 的 Trait 不是Interface,那是什么?
rust
花褪残红青杏小21 小时前
Rust图像处理第7节-马赛克像素化:分块取平均色实现打码风格
rust·webassembly·图形学
hez20101 天前
在 .NET 上构建超大托管数组
c#·.net·.net core·gc·clr
doiito2 天前
【Agent Harness】Gliding Horse 设计细节 -- 不跟风开发自己的AI Agent
架构·rust·agent
doiito2 天前
【Agent Harness】Gliding Horse 核心设计理念,不跟风开发自己的AI Agent
ai·rust·架构设计·系统设计·ai agent
花褪残红青杏小2 天前
Rust图像处理第6节- 均值模糊 & 中值模糊:3×3 邻域的两种经典玩法
rust·webassembly·图形学
子兮曰2 天前
前端工具链的「Rust 化」:一场没有赢家的军备竞赛?
前端·后端·rust
星栈2 天前
写 Dioxus Demo 不难,难的是把它写成项目
前端·rust·前端框架
mCell2 天前
【锐评】桌面端技术营销:别拿跑分当工程判断
前端·rust·electron
武子康3 天前
调查研究-201 Rust 里的 dev build 和 release build:为什么同一份代码性能差这么多?
后端·架构·rust