非同步特徵
Async methods in traits are were stabilized only recently, in the 1.75 release. This required support for using return-position impl Trait
(RPIT) in traits, as the desugaring for async fn
includes -> impl Future<Output = ...>
.
However, even with the native support today there are some pitfalls around async fn
and RPIT in traits:
-
Return-position impl Trait captures all in-scope lifetimes (so some patterns of borrowing cannot be expressed)
-
Traits whose methods use return-position
impl trait
orasync
are notdyn
compatible.
如果需要 dyn
支援,Crate async_trait 提供採用巨集的解決方法(但有些要注意的地方):
use async_trait::async_trait; use std::time::Instant; use tokio::time::{sleep, Duration}; #[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
語言支援的困難處涉及艱深的 Rust,可能不適合深入介紹。如有興趣深入探究,可以參閱 Niko Matsakis 的這篇文章,說明得相當清楚。 -
嘗試建立新的休眠程式結構體,讓該結構體隨機決定休眠時間長度,然後將其新增至 Vec。