Skip to content

异步

async fn 返回实现 Future 的匿名类型。.await 在 Future 完成前让出当前任务,不阻塞操作系统线程。Future 是惰性的:不被 .await 或执行器轮询就不会执行。

rust
async fn load(url: &str) -> Result<String, reqwest::Error> {
    reqwest::get(url).await?.text().await
}

异步函数内部才能 .await。同步代码要跑异步逻辑,必须经过运行时。

运行时

标准库不内置执行器。项目里通常用 Tokio:

toml
[dependencies]
tokio = { version = "1", features = ["full"] }
rust
#[tokio::main]
async fn main() {
    let body = load("https://example.com").await.unwrap();
    println!("{body}");
}

#[tokio::main] 启动运行时并阻塞到 async main 结束。库 crate 不要依赖某个运行时的 main 宏,把 async fn 交给调用方去驱动。

tokio::spawn 把任务放到运行时上并发执行,要求 Future 是 'static + Send。任务需要跨 .await 持有的数据必须能安全送到其他线程。

与所有权

.await 可能在任意 await 点让出,借用必须在整个 Future 的生命周期内成立。函数签名里不要返回指向局部变量的引用;跨 await 需要所有权时把数据 move 进任务,或用 Arc 共享。

rust
let name = String::from("demo");
tokio::spawn(async move {
    println!("{name}");
});

async move 捕获所有权。共享状态用 Arc<T>,可变共享再加 Mutex / RwLock(Tokio 的或 std 的,按是否跨 await 持锁选择)。

阻塞

运行时线程上不要做长时间同步阻塞(大计算、同步文件、同步数据库驱动)。这类工作放到 spawn_blocking 或专用线程池。CPU 密集与 I/O 密集不要挤在同一类 worker 上。

库若提供异步 API,公开 async fn 或返回 impl Future;不要在库内部偷偷 block_on

基于 MIT 许可发布