---
title: "Zig Async/Await: O Novo Sistema std.Io Explicado"
url: "https://ziglang.com.br/artigos/zig-async-await-novo-io/"
markdown_url: "https://ziglang.com.br/artigos/zig-async-await-novo-io.MD"
description: "Entenda o novo sistema async/await do Zig com std.Io: futures, cancelamento, modelos de concorrência e exemplos práticos. Guia completo em português."
date: "2026-04-01"
author: ""
---

# Zig Async/Await: O Novo Sistema std.Io Explicado

Entenda o novo sistema async/await do Zig com std.Io: futures, cancelamento, modelos de concorrência e exemplos práticos. Guia completo em português.


# Zig Async/Await: O Novo Sistema std.Io Explicado

O sistema de I/O assíncrono do Zig passou por uma reformulação completa. O antigo modelo de async/await — que havia sido temporariamente removido — voltou repensado do zero com o `std.Io`, uma interface que separa a **expressão de concorrência** do **modelo de execução**. O resultado? Código que funciona de forma ótima tanto em modo síncrono quanto assíncrono, sem precisar de duas versões da mesma biblioteca.

Neste artigo, vamos explorar como o novo `std.Io` funciona, por que ele é diferente de qualquer outro modelo async que você já viu, e como usá-lo na prática.

> Se você ainda não conhece Zig, comece por [O que é Zig](/tutoriais/o-que-e-zig/) ou veja [Por que aprender Zig](/artigos/por-que-aprender-zig/).

## O Problema que o std.Io Resolve

Em linguagens como JavaScript, Rust e Go, o modelo de concorrência é definido pela linguagem. Em JS, tudo é single-threaded com event loop. Em Go, tudo são goroutines. Em Rust, você escolhe um runtime (tokio, async-std), mas o código é "colorido" — funções async e sync são incompatíveis.

Zig tomou uma decisão radical: **o modelo de concorrência é injetado, não fixo**. Assim como o [allocator](/glossario/allocator/) é passado como parâmetro em Zig (em vez de usar `malloc` global), o `Io` também é passado como parâmetro. Isso significa que a mesma função pode rodar:

- **Bloqueante** — I/O síncrono direto, sem overhead
- **Thread pool** — multiplexando chamadas em threads do SO
- **Green threads** — usando [io_uring](/artigos/zig-io-uring-async/) no Linux
- **Coroutines stackless** — máquinas de estado, compatível com WebAssembly

## Anatomia do std.Io

O `std.Io` é uma interface que encapsula todas as operações de I/O: sistema de arquivos, rede, timers e sincronização. Veja a estrutura básica:

```zig
const std = @import("std");
const Io = std.Io;

pub fn main(io: Io) !void {
    const file = try Io.Dir.cwd().createFile(io, "dados.txt", .{});
    defer file.close(io);
    try file.writeAll(io, "Olá do Zig assíncrono!\n");
}
```

Repare que `io` é passado como parâmetro — exatamente como fazemos com [allocators](/glossario/allocator/). Não há nenhuma keyword `async` na assinatura da função. O código é **agnóstico ao modelo de concorrência**.

### Comparação com o Modelo Anterior

No antigo sistema (removido na versão 0.11), async/await eram keywords da linguagem com semântica fixa:

```zig
// ANTIGO — não funciona mais
const frame = async readFile("dados.txt");
const result = await frame;
```

O novo sistema é fundamentalmente diferente — a concorrência é expressa via a API `std.Io`, não via keywords do compilador.

## Futures e Concorrência

A grande novidade é o modelo de [futures](/glossario/comptime/). Quando você quer executar operações em paralelo, usa `io.async()`:

```zig
const std = @import("std");
const Io = std.Io;

fn salvarBackup(io: Io, dados: []const u8) !void {
    // Inicia duas operações em paralelo
    var future_local = io.async(salvarArquivo, .{ io, dados, "backup_local.dat" });
    var future_remoto = io.async(salvarArquivo, .{ io, dados, "backup_remoto.dat" });

    // Aguarda ambas completarem
    try future_local.await(io);
    try future_remoto.await(io);
}

fn salvarArquivo(io: Io, dados: []const u8, caminho: []const u8) !void {
    const file = try Io.Dir.cwd().createFile(io, caminho, .{});
    defer file.close(io);
    try file.writeAll(io, dados);
}
```

Esse código expressa que as duas operações de salvamento **podem** rodar em paralelo. Se o runtime fornecido for bloqueante, elas rodam sequencialmente. Se for green threads com [io_uring](/artigos/zig-io-uring-async/), rodam de verdade em paralelo. O código não muda.

### Cancelamento de Futures

Toda future suporta cancelamento, o que é essencial para operações com timeout ou para liberar recursos:

```zig
fn buscarComTimeout(io: Io, url: []const u8) ![]const u8 {
    var future = io.async(fazerRequisicao, .{ io, url });
    defer future.cancel(io) catch {};

    // Se demorar demais, o defer cancela automaticamente
    const resultado = try future.await(io);
    return resultado;
}
```

O padrão `defer future.cancel()` garante que a operação é cancelada se a função sair por qualquer motivo — erro, retorno antecipado ou [errdefer](/glossario/errdefer/).

## Modelos de Execução

A beleza do `std.Io` é que você escolhe o modelo na hora de rodar, não na hora de escrever. Veja os quatro modelos disponíveis:

### 1. Blocking I/O

O mais simples. Cada chamada de I/O bloqueia a thread atual:

```zig
pub fn main() !void {
    var io = std.Io.blocking();
    try meuServidor(io);
}
```

Perfeito para CLIs, scripts e ferramentas de [build](/artigos/zig-build-system-guia/). Zero overhead, zero alocações extras.

### 2. Thread Pool

Multiplica operações bloqueantes em threads do SO:

```zig
pub fn main() !void {
    var io = std.Io.threadPool(.{ .thread_count = 8 });
    defer io.deinit();
    try meuServidor(io);
}
```

Bom para servidores com carga moderada. Cada future pode rodar em uma thread diferente.

### 3. Green Threads (io_uring)

No Linux, usa [io_uring](/artigos/zig-io-uring-async/) para I/O assíncrono de verdade com green threads leves:

```zig
pub fn main() !void {
    var io = std.Io.greenThreads(.{ .entries = 256 });
    defer io.deinit();
    try meuServidor(io);
}
```

Essa é a opção mais performática para servidores de alta carga. Milhares de conexões simultâneas com uso mínimo de memória — semelhante ao que o [TigerBeetle](/ecossistema/tigerbeetle-database/) faz em produção.

### 4. Stackless Coroutines

Transforma futures em máquinas de estado, compatível com ambientes sem stack como [WebAssembly](/artigos/zig-webassembly-2026/):

```zig
pub fn main() !void {
    var io = std.Io.stackless();
    defer io.deinit();
    try meuServidor(io);
}
```

Ideal para [aplicações WASM](/artigos/zig-webassembly-2026/) e [sistemas embarcados](/ecossistema/zig-embedded-hal/) onde a memória é limitada.

## Exemplo Prático: Servidor HTTP Concorrente

Vamos juntar tudo em um servidor HTTP que aceita múltiplas conexões:

```zig
const std = @import("std");
const Io = std.Io;
const net = std.net;

fn handleCliente(io: Io, conn: net.StreamServer.Connection) !void {
    defer conn.stream.close(io);

    var buf: [4096]u8 = undefined;
    const n = try conn.stream.read(io, &buf);

    const resposta =
        "HTTP/1.1 200 OK\r\n" ++
        "Content-Type: text/plain\r\n" ++
        "Content-Length: 11\r\n\r\n" ++
        "Olá, Zig!\n";

    try conn.stream.writeAll(io, resposta);
}

fn servidor(io: Io) !void {
    var server = net.StreamServer.init(io, .{});
    defer server.deinit(io);

    try server.listen(io, net.Address.parseIp("0.0.0.0", 8080));

    while (true) {
        const conn = try server.accept(io);
        // Cada cliente é tratado concorrentemente
        var _ = io.async(handleCliente, .{ io, conn });
    }
}

pub fn main() !void {
    // Escolha o modelo adequado ao seu ambiente
    var io = std.Io.greenThreads(.{ .entries = 256 });
    defer io.deinit();
    try servidor(io);
}
```

Compare isso com o [tutorial de servidor HTTP](/tutoriais/zig-http-server/) que usa o modelo síncrono. A lógica é praticamente a mesma — a única diferença é o parâmetro `io`.

## Function Color Blindness

O termo "function coloring" vem do [famoso artigo de Bob Nystrom](https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/). Em Rust, funções `async fn` são "vermelhas" e funções normais são "azuis" — você não pode chamar uma vermelha de dentro de uma azul sem um runtime.

O Zig resolve isso completamente. Não existe distinção entre funções "async" e "sync". Toda função que recebe `Io` pode ser usada em qualquer contexto. Isso elimina:

- Duplicação de código (versão sync + async)
- Incompatibilidade entre bibliotecas
- Necessidade de escolher runtime na hora de compilar

Para quem vem de Rust, compare com o [artigo Zig para desenvolvedores Rust](/artigos/zig-para-desenvolvedores-rust/). E se quiser entender como Go aborda concorrência de forma diferente, veja o modelo de goroutines em <a href="https://golang.com.br/aprenda/concorrencia-go/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', { destination: 'golang.com.br' })">golang.com.br</a>.

## Impacto no Ecossistema

O novo `std.Io` muda fundamentalmente como bibliotecas Zig são escritas:

1. **Uma biblioteca, múltiplos runtimes** — pacotes como [httpz](/ecossistema/httpz-web/) funcionam automaticamente com qualquer modelo de I/O
2. **Testabilidade** — injete um `Io` mock nos [testes](/artigos/zig-testes-guia-completo/) para simular I/O sem tocar o disco
3. **Portabilidade** — o mesmo código roda no Linux (io_uring), macOS (kqueue), Windows (IOCP) e [WebAssembly](/artigos/zig-webassembly-2026/)
4. **Composição** — combine bibliotecas que usam diferentes modelos sem conflito

Veja mais sobre o ecossistema de [bibliotecas de rede do Zig](/ecossistema/zig-network/) e [clientes HTTP](/ecossistema/zig-http-clients/).

## Quando Usar Cada Modelo

| Cenário | Modelo Recomendado | Por quê |
|---------|-------------------|---------|
| CLI / Scripts | Blocking | Zero overhead, simplicidade |
| API REST | Green Threads | Alta concorrência, baixa latência |
| [Jogos](/artigos/zig-raylib-jogos/) | Thread Pool | Controle preciso de threads |
| [WASM](/artigos/zig-webassembly-2026/) | Stackless | Sem stack, compatível com browsers |
| [Embarcados](/ecossistema/zig-embedded-hal/) | Blocking ou Stackless | Memória limitada |
| [Microserviços](/artigos/zig-microservicos/) | Green Threads | Milhares de conexões |

## Conclusão

O novo `std.Io` do Zig é uma das inovações mais importantes em design de linguagens de programação de sistemas. Ao tratar I/O como uma dependência injetável — assim como memória com [allocators](/glossario/allocator/) — o Zig elimina o problema de "function coloring" e permite que o mesmo código funcione de forma ótima em qualquer modelo de concorrência.

Se você quer se aprofundar, explore o [tutorial de concorrência em Zig](/tutoriais/concorrencia-em-zig/), o artigo sobre [io_uring](/artigos/zig-io-uring-async/), e o [cheatsheet de concorrência](/cheatsheets/concorrencia/). Para comparar com a abordagem de <a href="https://rustlang.com.br/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', { destination: 'rustlang.com.br' })">Rust para async/await</a>, veja nosso [comparativo Zig vs Rust](/artigos/zig-vs-rust/).

Também recomendamos o novo artigo sobre [Zig para sistemas embarcados e IoT](/artigos/zig-embarcados-iot/), onde o `std.Io` com modo stackless brilha especialmente.
