Writer Interface em Zig — O que é e Como Usar
Definição
A Writer interface em Zig é o padrão utilizado pela biblioteca padrão para abstração de escrita de dados. Qualquer tipo que forneça uma função write com a assinatura correta pode ser usado como Writer. Isso permite escrever código genérico que funciona com stdout, arquivos, buffers em memória, sockets de rede ou qualquer outro destino de dados.
Em Zig, interfaces são implementadas via anytype (duck typing em comptime) ou via o tipo concreto std.io.Writer, que usa uma vtable para dispatch dinâmico.
Por que Writer Interface Importa
- Código genérico: Uma função que aceita
anytypewriter funciona com qualquer destino. - Testabilidade: Escrever em buffer para testes, em arquivo para produção.
- Composição: Writers podem ser encadeados (buffered writer, counting writer, etc.).
- Padrão da std lib: Formatação, logging e serialização usam a Writer interface.
Exemplo Prático
Função Genérica com Writer
const std = @import("std");
fn escreverRelatorio(writer: anytype, nome: []const u8, pontos: u32) !void {
try writer.print("Relatório de: {s}\n", .{nome});
try writer.print("Pontuação: {}\n", .{pontos});
try writer.print("Status: {s}\n", .{
if (pontos >= 70) "Aprovado" else "Reprovado",
});
try writer.writeAll("---\n");
}
pub fn main() !void {
// Escrever para stdout
const stdout = std.io.getStdOut().writer();
try escreverRelatorio(stdout, "Ana", 85);
try escreverRelatorio(stdout, "Bruno", 60);
}
Escrever em Buffer (para Testes)
const std = @import("std");
fn formatarSaudacao(writer: anytype, nome: []const u8) !void {
try writer.print("Olá, {s}!", .{nome});
}
test "formatar saudação" {
var buffer: [256]u8 = undefined;
var stream = std.io.fixedBufferStream(&buffer);
const writer = stream.writer();
try formatarSaudacao(writer, "Zig Brasil");
const resultado = stream.getWritten();
try std.testing.expectEqualStrings("Olá, Zig Brasil!", resultado);
}
Buffered Writer para Performance
const std = @import("std");
pub fn main() !void {
const arquivo = try std.fs.cwd().createFile("saida.txt", .{});
defer arquivo.close();
// Buffered writer reduz syscalls de escrita
var buf_writer = std.io.bufferedWriter(arquivo.writer());
const writer = buf_writer.writer();
for (0..1000) |i| {
try writer.print("Linha {}\n", .{i});
}
// Flush final para garantir que tudo foi escrito
try buf_writer.flush();
}
Writers Comuns na std lib
| Writer | Descrição |
|---|---|
std.io.getStdOut().writer() | Saída padrão (stdout) |
std.io.getStdErr().writer() | Saída de erro (stderr) |
file.writer() | Escrita em arquivo |
stream.writer() | Escrita em fixedBufferStream |
std.io.bufferedWriter(w) | Writer com buffer |
std.io.countingWriter(w) | Writer que conta bytes escritos |
Armadilhas Comuns
- Flush: Buffered writers exigem
flush()no final para garantir que dados pendentes sejam escritos. - Erros de escrita: Sempre trate os erros com
try. Escrever pode falhar (disco cheio, socket fechado). - anytype vs Writer concreto: Use
anytypepara funções simples. Usestd.io.Writerquando precisar armazenar o writer em uma struct. - Performance: Sem buffer, cada
printpode gerar uma syscall. UsebufferedWriterpara escrita intensiva.
Termos Relacionados
- Reader Interface — Interface de leitura complementar
- anytype — Mecanismo de genéricos usado pela interface
- Vtable Interface — Dispatch dinâmico para armazenar writers
- Error Union — Writers retornam
!voidou!usize