<h2>Entendendo Async e Await em Rust</h2>
<p>A programação assíncrona permite que seu programa execute múltiplas operações sem bloquear a thread principal. Ao contrário de linguagens como JavaScript, Rust não oferece async por padrão — você precisa de um runtime como Tokio para executar código assíncrono. A sintaxe <code>async</code> cria uma função que retorna uma <code>Future</code>, um objeto que representa um valor que será computado em algum momento no futuro. O <code>await</code> pausa a execução até que essa <code>Future</code> seja resolvida.</p>
<p>Compreender a diferença entre código síncrono (bloqueante) e assíncrono (não-bloqueante) é fundamental. Uma chamada de rede síncrona congela toda a aplicação enquanto aguarda a resposta. Com async/await, você pode atender múltiplos requests simultaneamente usando uma única thread, tornando a aplicação muito mais eficiente. Rust garante segurança com seu sistema de tipos — as <code>Futures</code> são <code>Send</code> e <code>Sync</code> quando apropriado, prevenindo bugs de concorrência em tempo de compilação.</p>
<pre><code class="language-rust">use tokio::time::{sleep, Duration};
#[tokio::main]
async fn main() {
println!("Iniciando...");
wait_and_print().await;
println!("Finalizado!");
}
async fn wait_and_print() {
sleep(Duration::from_secs(2)).await;
println!("Acordei após 2 segundos!");
}</code></pre>
<h2>Futures e o Padrão de Execução</h2>
<p>Uma <code>Future</code> em Rust é um trait que descreve uma computação assíncrona. Diferente de Promises em JavaScript, Futures em Rust são lazy — não executam até serem "polled" (consultadas) pelo runtime. Quando você chama uma função <code>async</code>, ela retorna uma <code>Future</code> não iniciada. Apenas quando você a aguarda com <code>.await</code> é que ela começa a execução sob demanda.</p>
<p>O ciclo de vida de uma <code>Future</code> passa por polling repetido até estar pronta (<code>Poll::Ready</code>) ou ainda pendente (<code>Poll::Pending</code>). O runtime gerencia esse polling para você. Isso é crucial: você não precisa entender o mecanismo interno de polling para usar async/await, mas entender que Futures são lazy ajuda a escrever código correto.</p>
<pre><code class="language-rust">use futures::future::join_all;
async fn fetch_user(id: u32) -> String {
println!("Buscando usuário {}", id);
tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
format!("Usuário {}", id)
}
#[tokio::main]
async fn main() {
let futures = vec![
fetch_user(1),
fetch_user(2),
fetch_user(3),
];
let results = join_all(futures).await;
println!("Resultados: {:?}", results);
}</code></pre>
<h2>Trabalhando com Múltiplas Tasks</h2>
<p>Para executar operações realmente concorrentes, use <code>tokio::spawn</code> para criar tasks (tarefas) que rodam independentemente. Ao contrário de threads do SO, tasks são muito leves e você pode criar milhares delas. Cada task é uma <code>Future</code> que executa no runtime de Tokio, compartilhando a mesma ou as mesmas threads.</p>
<p>A diferença entre <code>await</code> simples e <code>spawn</code> é importante: <code>await</code> pausa o ponto atual aguardando um resultado sequencial. <code>spawn</code> lança a task imediatamente e continua — você obtém um <code>JoinHandle</code> para aguardar o resultado depois. Para sincronizar múltiplas tasks, use <code>join!</code> do Tokio ou <code>select!</code> para aguardar a primeira que terminar.</p>
<pre><code class="language-rust">#[tokio::main]
async fn main() {
let handle1 = tokio::spawn(async {
tokio::time::sleep(tokio::time::Duration::from_secs(2)).await;
"Task 1 completa"
});
let handle2 = tokio::spawn(async {
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
"Task 2 completa"
});
let result1 = handle1.await.unwrap();
let result2 = handle2.await.unwrap();
println!("{}, {}", result1, result2);
}</code></pre>
<h2>Tratamento de Erros em Código Assíncrono</h2>
<p>Erros em async funcionam como em código síncrono: <code>Result<T, E></code> é o padrão. A diferença é que você frequentemente lida com erros em múltiplas operações concorrentes. Se uma task falhar, outras continuam — você precisa decidir se quer falhar rápido ou coletar todos os resultados e tratá-los depois.</p>
<p>Para operações críticas onde um erro deve parar tudo, use o operador <code>?</code> normalmente. Para coletar resultados parciais, itere sobre os <code>JoinHandle</code>s e trate cada <code>Result</code>. Sempre use <code>unwrap()</code> com cautela em código de produção — prefira logging e propagação adequada de erros.</p>
<pre><code class="language-rust">use tokio::fs;
async fn read_file(path: &str) -> Result<String, std::io::Error> {
fs::read_to_string(path).await
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let content = read_file("arquivo.txt").await?;
println!("Conteúdo: {}", content);
Ok(())
}</code></pre>
<h2>Conclusão</h2>
<p>Você aprendeu que <strong>async/await em Rust permite escrever código não-bloqueante que se parece com código síncrono</strong>, mantendo segurança em tempo de compilação. Futures são lazy e executadas sob polling — não confunda com threads. Use <code>tokio::spawn</code> para paralelismo real, mas lembre-se que <code>await</code> sequencial ainda é útil quando você precisa que uma operação termine antes da próxima começar. Finalmente, <strong>Rust força você a tratar erros explicitamente em código assíncrono</strong>, o que previne bugs sutis encontrados em outras linguagens. Pratique combinando <code>spawn</code>, <code>join!</code> e <code>select!</code> para dominar padrões de concorrência.</p>
<h2>Referências</h2>
<ul>
<li><a href="https://tokio.rs/" target="_blank" rel="noopener noreferrer">Tokio Official Documentation</a></li>
<li><a href="https://rust-lang.github.io/async-book/" target="_blank" rel="noopener noreferrer">Rust Async Book</a></li>
<li><a href="https://docs.rs/futures/" target="_blank" rel="noopener noreferrer">Futures Documentation on Docs.rs</a></li>
<li><a href="https://aturon.github.io/blog/2016/08/11/futures/" target="_blank" rel="noopener noreferrer">Understanding Rust Futures by Aaron Turon</a></li>
<li><a href="https://medium.com/swlh/rust-async-await-in-practice-e4e37c8e3b5" target="_blank" rel="noopener noreferrer">Async Rust in Practice - Medium</a></li>
</ul>