4.3 异步 Trait
03-异步 Trait — Comprehensive Rust
译文 · 基于 Comprehensive Rust
原文链接: https://google.github.io/comprehensive-rust/concurrency/async-pitfalls/async-traits.html
4.3 异步 Trait
Trait 中的异步方法在 1.75 版本中稳定。这需要支持在 trait 中使用返回位置的 impl Trait,因为 async fn 的脱糖包含 -> impl Future<Output = ...>。
不过,即便有原生支持,围绕 async fn 仍有特定陷阱:
async_trait crate 通过宏为 dyn 支持提供变通方法,但有特定注意事项:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
| // Copyright 2024 Google LLC
// SPDX-License-Identifier: Apache-2.0
use async_trait::async_trait;
use std::time::Instant;
use tokio::time::{Duration, sleep};
#[async_trait]
trait Sleeper {
async fn sleep(&self);
}
struct FixedSleeper {
sleep_ms: u64,
}
#[async_trait]
impl Sleeper for FixedSleeper {
async fn sleep(&self) {
sleep(Duration::from_millis(self.sleep_ms)).await;
}
}
async fn run_all_sleepers_multiple_times(
sleepers: Vec<Box<dyn Sleeper>>,
n_times: usize,
) {
for _ in 0..n_times {
println!("Running all sleepers...");
for sleeper in &sleepers {
let start = Instant::now();
sleeper.sleep().await;
println!("Slept for {} ms", start.elapsed().as_millis());
}
}
}
#[tokio::main]
async fn main() {
let sleepers: Vec<Box<dyn Sleeper>> = vec![
Box::new(FixedSleeper { sleep_ms: 50 }),
Box::new(FixedSleeper { sleep_ms: 100 }),
];
run_all_sleepers_multiple_times(sleepers, 5).await;
}
|
async_trait 易于使用,但注意它通过堆分配实现这一点。堆分配有性能开销。
语言对 async trait 支持的挑战太深,本课无法深入描述。若有兴趣深挖,参见 Niko Matsakis 的这篇博文。也可参见这些关键词:
试着创建一个休眠随机时长的新 sleeper 结构体,并把它加入 Vec。