Async in Rust
Async enables concurrent I/O without blocking threads. async transforms functions into state machines returning futures.
async/await basics
async fn fetch() -> reqwest::Result<String> {
let text = reqwest::get("https://example.com").await?.text().await?;
Ok(text)
}
async fn returns impl Future<Output = T>. .await yields until the future is ready.
Runtimes
Use an executor like tokio or async-std to drive futures.
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let a = fetch();
let b = fetch();
let (ra, rb) = tokio::join!(a, b); // concurrent
println!("{}{}", ra?, rb?);
Ok(())
}
Spawning tasks and cancellation
let handle = tokio::spawn(async { 42 });
let val = handle.await?;
Use tokio::select! to race tasks or add timeouts.
Avoid blocking
Do not call blocking APIs in async contexts. Use spawn_blocking for CPU‑bound work.
let result = tokio::task::spawn_blocking(|| do_cpu_work()).await?;
Traits and async
You cannot have async trait methods directly on stable without async-trait or GATs patterns. Prefer returning impl Future or use async-trait crate with care.
Streams
For sequences of async values, use futures::stream or tokio_stream and Stream trait.
Summary
async fnreturns a future;.awaitdrives it- Use a runtime (tokio) to run tasks; avoid blocking calls
- Compose concurrency with
join!/select!and prefer structured cancellation