Skip to content

新语言特性

> 掌握 Rust 2024 Edition 引入的重要新特性。

异步闭包

问题场景

在 Rust 2024 之前,异步闭包需要变通方案:

rust
// ❌ Rust 2021: 异步闭包不支持
let async_closure = async |x| {  // 编译错误
    some_async_fn(x).await
};

// ✅ 变通方案:使用 async 块
let closure = |x| async {
    some_async_fn(x).await
};
▶ Run

Rust 2024: 原生异步闭包

rust
// ✅ Rust 2024: 原生支持异步闭包
let async_closure = async |x: i32| -> i32 {
    some_async_fn(x).await
};

// 使用异步闭包
let result = async_closure(42).await;
▶ Run

异步闭包语法

rust
// 1. 基本语法
let f = async || {
    // 异步代码
};

// 2. 带参数
let add = async |a: i32, b: i32| {
    async_add(a, b).await
};

// 3. 带返回类型标注
let process = async |data: Vec<u8>| -> Result<String, Error> {
    parse_async(data).await
};

// 4. move 关键字
let value = 42;
let closure = async move || {
    consume(value).await  // value 被移动到闭包中
};
▶ Run

实际应用

rust
use tokio::net::TcpStream;
use tokio::io::{AsyncReadExt, AsyncWriteExt};

// ✅ 使用异步闭包创建处理器
let handle_client = async |mut stream: TcpStream| {
    let mut buf = [0; 1024];
    let n = stream.read(&mut buf).await?;
    stream.write_all(&buf[..n]).await?;
    Ok::<_, std::io::Error>(())
};

// 批量处理连接
let handlers: Vec<_> = connections
    .into_iter()
    .map(handle_client)
    .collect();

futures::future::join_all(handlers).await;
▶ Run

impl Trait 改进

返回位置 impl Trait

rust
// Rust 2021: impl Trait 只能在返回位置
fn get_iter() -> impl Iterator<Item = i32> {
    vec![1, 2, 3].into_iter()
}

// Rust 2024: 更灵活的使用场景
fn conditional_iter(condition: bool) -> impl Iterator<Item = i32> {
    if condition {
        vec![1, 2, 3].into_iter()
    } else {
        vec![4, 5, 6].into_iter()
    }
}
▶ Run

参数位置 impl Trait

rust
// ✅ Rust 2024: 参数位置使用 impl Trait
fn process(data: impl IntoIterator<Item = i32>) -> i32 {
    data.into_iter().sum()
}

// 等价于泛型函数,但语法更简洁
fn process_generic<T: IntoIterator<Item = i32>>(data: T) -> i32 {
    data.into_iter().sum()
}

// 调用
process(vec![1, 2, 3]);
process([1, 2, 3]);
process(1..=3);
▶ Run

impl Trait 与生命周期

rust
// ✅ Rust 2024: 更好的生命周期推断
fn filter_positive<'a>(
    data: &'a [i32]
) -> impl Iterator<Item = i32> + 'a {
    data.iter().copied().filter(|&x| x > 0)
}

// 使用 RPITIT(Return Position Impl Trait In Trait)
trait DataProcessor {
    fn process(&self, data: &[i32]) -> impl Iterator<Item = i32>;
}

struct MyProcessor;

impl DataProcessor for MyProcessor {
    fn process(&self, data: &[i32]) -> impl Iterator<Item = i32> {
        data.iter().copied().filter(|&x| x > 0)
    }
}
▶ Run

捕获规则改进

rust
// Rust 2021: impl Trait 捕获所有泛型参数
fn foo<T>(x: T) -> impl Sized { x }

// Rust 2024: 更精确的捕获控制
fn bar<T>(x: T) -> impl Sized + use<T> { x }
//             显式声明捕获 T ^^^^^

// 示例:避免不必要的捕获
fn process(data: Vec<i32>) -> impl Iterator<Item = i32> {
    data.into_iter().filter(|x| *x > 0)
    // 只捕获 Item = i32,不捕获其他类型参数
}
▶ Run

模式匹配增强

if let 模式链

rust
// ✅ Rust 2024: 支持多个 if let 模式
fn process_value(value: Option<Result<i32, String>>) {
    if let Some(Ok(n)) = value {
        println!("Got value: {}", n);
    }
    
    // 链式模式匹配
    if let Some(Ok(n)) = value
        && n > 0
        && n < 100
    {
        println!("Valid positive number: {}", n);
    }
}
▶ Run

let-else 模式

rust
// ✅ let-else 语法
fn process(input: Option<i32>) -> Result<i32, String> {
    let Some(value) = input else {
        return Err("No value provided".to_string());
    };
    
    let checked = if value > 0 { value } else {
        return Err("Value must be positive".to_string());
    };
    
    Ok(checked * 2)
}
▶ Run

模式中的 or 模式

rust
// ✅ Rust 2024: or 模式增强
enum Color {
    Rgb(u8, u8, u8),
    Hsv(u8, u8, u8),
}

fn is_red(color: Color) -> bool {
    match color {
        Color::Rgb(255, 0, 0) | Color::Rgb(255, _, _) => true,
        Color::Hsv(0, 100, 100) => true,
        _ => false,
    }
}

// 绑定变量
fn get_brightness(color: Color) -> u8 {
    match color {
        Color::Rgb(_, _, b) | Color::Hsv(_, _, b) => b,
        //         相同变量名 ^^^^^
    }
}
▶ Run

范围模式

rust
// ✅ Rust 2024: 更强大的范围模式
fn classify(value: i32) -> &'static str {
    match value {
        0..=9 => "single digit",
        10..=99 => "double digit",
        100..=999 => "triple digit",
        _ => "large number",
    }
}

// 字符范围
fn is_vowel(c: char) -> bool {
    matches!(c, 'a'..='z' | 'A'..='Z')
}
▶ Run

其他改进

1. gen 闭包(实验性)

rust
// ✅ Rust 2024: gen 闭包(需要 feature gate)
#![feature(gen_blocks)]

fn generate_numbers() -> impl Iterator<Item = i32> {
    gen {
        let mut i = 0;
        loop {
            yield i;
            i += 1;
        }
    }
}
▶ Run

2. unsafe 操作符

rust
// ✅ Rust 2024: 更明确的 unsafe 标记
let value = unsafe { *ptr };  // 显式的 unsafe 块

// unsafe 函数调用
unsafe fn dangerous() {}

unsafe {
    dangerous();  // 必须在 unsafe 块中调用
}
▶ Run

3. format_args_capture

rust
// ✅ Rust 2024: 在格式化字符串中捕获变量
let name = "Alice";
let age = 30;

// 旧方式
println!("Name: {}, Age: {}", name, age);

// 新方式:直接捕获
println!("Name: {name}, Age: {age}");
//        直接使用变量名 ^^^^  ^^^
▶ Run

迁移建议

利用新特性的重构

rust
// ❌ Rust 2021
fn get_data() -> Box<dyn Iterator<Item = i32>> {
    Box::new(vec![1, 2, 3].into_iter())
}

// ✅ Rust 2024
fn get_data() -> impl Iterator<Item = i32> {
    vec![1, 2, 3].into_iter()
}
▶ Run

简化错误处理

rust
// ❌ Rust 2021: 嵌套 match
fn process(data: Option<Result<i32, Error>>) -> Result<i32, Error> {
    match data {
        Some(result) => match result {
            Ok(value) => Ok(value),
            Err(e) => Err(e),
        },
        None => Err(Error::NoData),
    }
}

// ✅ Rust 2024: 链式 if let
fn process(data: Option<Result<i32, Error>>) -> Result<i32, Error> {
    let Some(Ok(value)) = data else {
        return Err(Error::NoData);
    };
    Ok(value)
}
▶ Run

最佳实践

1. 使用异步闭包替代闭包返回 future

rust
// ❌ 旧方式
let handler = |x| async move {
    process(x).await
};

// ✅ 新方式
let handler = async |x| {
    process(x).await
};
▶ Run

2. 优先使用 impl Trait

rust
// ❌ 返回具体类型
fn get_iter() -> std::vec::IntoIter<i32> {
    vec![1, 2, 3].into_iter()
}

// ✅ 返回 impl Trait
fn get_iter() -> impl Iterator<Item = i32> {
    vec![1, 2, 3].into_iter()
}
▶ Run

3. 利用模式匹配简化代码

rust
// ❌ 多层嵌套
if let Some(x) = option {
    if x > 0 {
        if x < 100 {
            // ...
        }
    }
}

// ✅ 链式模式
if let Some(x) = option
    && x > 0
    && x < 100
{
    // ...
}
▶ Run

小结

Rust 2024 Edition 的关键改进:

特性用途优势
异步闭包定义异步闭包更自然的异步代码
impl Trait 增强类型抽象简化泛型代码
模式匹配增强条件匹配减少嵌套,更清晰
格式化捕获格式化字符串减少重复参数

迁移提示:

  • 大部分代码无需修改即可迁移
  • 使用 cargo fix --edition 自动修复
  • 逐步采用新特性改进代码

下一步: 下一节我们将学习现代 crate 生态的最佳实践。

练习

练习 1:异步闭包

编写一个异步闭包,模拟并发请求:

rust
// TODO: 实现 fetch_all 函数
async fn fetch_all(urls: Vec<&str>) -> Vec<Result<String, Error>> {
    // 使用异步闭包并发请求
}
▶ Run

练习 2:impl Trait

重构以下函数,使用 impl Trait:

rust
// 提示:简化返回类型
fn get_numbers() -> std::vec::IntoIter<i32> {
    vec![1, 2, 3, 4, 5].into_iter()
}
▶ Run

练习 3:模式匹配

使用链式 if let 重构以下代码:

rust
fn process(data: Option<Result<i32, String>>) {
    match data {
        Some(Ok(n)) if n > 0 => println!("Positive: {}", n),
        _ => println!("Invalid"),
    }
}
▶ Run