Programação Assíncrona em Rust: Guia Prático Completo

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução à Programação Assíncrona em Rust



Aplicações modernas exigem cada vez mais alto desempenho ao trabalhar com rede, sistema de arquivos ou bancos de dados. A programação assíncrona em Rust permite processar eficientemente milhares de conexões simultâneas sem criar threads para cada tarefa. Ao contrário do multithreading, o código assíncrono usa menos memória e escala melhor.



Rust oferece uma abordagem única para assincronia, baseada em abstrações de custo zero. Isso significa que você paga apenas pelo que usa — sem sobrecarga para funcionalidades não utilizadas. Neste guia, abordaremos os conceitos-chave e escreveremos exemplos práticos que ajudarão você a começar a escrever código assíncrono em Rust hoje mesmo.



Fundamentos de async/await e Futures



O que é Future?



Future é uma trait que representa uma operação assíncrona que pode ser concluída no futuro. Em Rust, Future é uma entidade preguiçosa: ela não faz nada até ser consultada (poll). A ideia principal: em vez de bloquear uma thread, registramos uma tarefa e obtemos o resultado quando ele estiver pronto.



use std::future::Future;use std::pin::Pin;use std::task::{Context, Poll};

struct MyFuture { ready: bool,}

impl Future for MyFuture { type Output = u32;

fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<u32> { if self.ready { Poll::Ready(42) } else { // Registra o waker para nova consulta cx.waker().wake_by_ref(); Poll::Pending } }}


async/await — Açúcar Sintático



A palavra-chave async transforma uma função ou bloco em um Future. await pausa a execução até a conclusão do Future, devolvendo o controle ao runtime.



use tokio::time::{sleep, Duration};

async fn fetch_data() -> String { // Simulação de requisição de rede sleep(Duration::from_secs(2)).await; String::from("Dados obtidos")}

#[tokio::main]async fn main() { let result = fetch_data().await; println!("{}", result);}


Ciclos de Vida e Borrow Checker



Uma das características do Rust é o controle rigoroso de empréstimos. No código assíncrono, isso é especialmente importante, pois um Future pode viver mais que os dados emprestados. Use async move para capturar a posse:



async fn process_data(data: Vec<u32>) -> u32 {    data.iter().sum()}

#[tokio::main]async fn main() { let numbers = vec![1, 2, 3, 4, 5]; let sum = process_data(numbers).await; println!("Soma: {}", sum);}


Trabalho Prático com Tokio



Instalação e Configuração



Tokio é o runtime assíncrono mais popular para Rust. Adicione ao Cargo.toml:



[dependencies]tokio = { version = "1", features = ["full"] }


Criando um Servidor TCP Assíncrono



Vamos considerar um servidor echo simples, que aceita conexões e envia de volta os dados recebidos:



use tokio::net::TcpListener;use tokio::io::{AsyncReadExt, AsyncWriteExt};

#[tokio::main]async fn main() -> Result<(), Box<dyn std::error::Error>> { let listener = TcpListener::bind("127.0.0.1:8080").await?; println!("Servidor iniciado na porta 8080");

loop { let (mut socket, addr) = listener.accept().await?; println!("Nova conexão de: {}", addr);

tokio::spawn(async move { let mut buf = [0; 1024]; loop { let n = socket.read(&mut buf).await.unwrap(); if n == 0 { break; } // Conexão fechada socket.write_all(&buf[..n]).await.unwra

Blogs

Book Recommendations