主题
异步
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。
