Como Ler Variáveis de Ambiente em Zig

Introdução

Variáveis de ambiente são uma forma padrão de configurar aplicações sem modificar código. Elas são usadas para definir caminhos, credenciais, modo de execução e outras configurações. Em Zig, você pode acessar variáveis de ambiente através de std.posix.getenv() e std.process.getEnvMap().

Nesta receita, você aprenderá a ler e utilizar variáveis de ambiente em seus programas.

Pré-requisitos

Ler uma Variável de Ambiente

const std = @import("std");

pub fn main() !void {
    // Ler variável HOME
    if (std.posix.getenv("HOME")) |home| {
        std.debug.print("HOME: {s}\n", .{home});
    } else {
        std.debug.print("HOME não definida\n", .{});
    }

    // Ler variável PATH
    if (std.posix.getenv("PATH")) |path_val| {
        std.debug.print("PATH: {s}\n", .{path_val});
    }

    // Ler variável USER
    if (std.posix.getenv("USER")) |user| {
        std.debug.print("USER: {s}\n", .{user});
    }

    // Variável que pode não existir
    if (std.posix.getenv("MINHA_VARIAVEL")) |val| {
        std.debug.print("MINHA_VARIAVEL: {s}\n", .{val});
    } else {
        std.debug.print("MINHA_VARIAVEL não definida\n", .{});
    }
}

Variável com Valor Padrão

const std = @import("std");

fn getEnvOuPadrao(nome: []const u8, padrao: []const u8) []const u8 {
    return std.posix.getenv(nome) orelse padrao;
}

pub fn main() !void {
    const porta = getEnvOuPadrao("PORT", "8080");
    const host = getEnvOuPadrao("HOST", "localhost");
    const modo = getEnvOuPadrao("MODE", "development");
    const log_level = getEnvOuPadrao("LOG_LEVEL", "info");

    std.debug.print("Configuração do servidor:\n", .{});
    std.debug.print("  Host: {s}\n", .{host});
    std.debug.print("  Porta: {s}\n", .{porta});
    std.debug.print("  Modo: {s}\n", .{modo});
    std.debug.print("  Log: {s}\n", .{log_level});
}

Listar Todas as Variáveis de Ambiente

const std = @import("std");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    // Obter mapa de todas as variáveis
    var env_map = try std.process.getEnvMap(allocator);
    defer env_map.deinit();

    std.debug.print("Variáveis de ambiente ({d} total):\n", .{env_map.count()});

    var it = env_map.iterator();
    var count: usize = 0;
    while (it.next()) |entry| {
        if (count < 10) { // Mostrar apenas as 10 primeiras
            std.debug.print("  {s} = {s}\n", .{ entry.key_ptr.*, entry.value_ptr.* });
        }
        count += 1;
    }
    if (count > 10) {
        std.debug.print("  ... e mais {d} variáveis\n", .{count - 10});
    }
}

Configuração de Aplicação via Ambiente

const std = @import("std");

const AppConfig = struct {
    host: []const u8,
    porta: u16,
    debug: bool,
    db_url: []const u8,
    max_conexoes: u32,

    pub fn fromEnv() AppConfig {
        const porta_str = std.posix.getenv("APP_PORT") orelse "3000";
        const porta = std.fmt.parseInt(u16, porta_str, 10) catch 3000;

        const max_str = std.posix.getenv("APP_MAX_CONN") orelse "100";
        const max_conn = std.fmt.parseInt(u32, max_str, 10) catch 100;

        const debug_str = std.posix.getenv("APP_DEBUG") orelse "false";
        const debug = std.mem.eql(u8, debug_str, "true") or std.mem.eql(u8, debug_str, "1");

        return .{
            .host = std.posix.getenv("APP_HOST") orelse "0.0.0.0",
            .porta = porta,
            .debug = debug,
            .db_url = std.posix.getenv("DATABASE_URL") orelse "sqlite://local.db",
            .max_conexoes = max_conn,
        };
    }

    pub fn imprimir(self: AppConfig) void {
        std.debug.print("=== Configuração da Aplicação ===\n", .{});
        std.debug.print("  Host: {s}\n", .{self.host});
        std.debug.print("  Porta: {d}\n", .{self.porta});
        std.debug.print("  Debug: {}\n", .{self.debug});
        std.debug.print("  DB URL: {s}\n", .{self.db_url});
        std.debug.print("  Max Conexões: {d}\n", .{self.max_conexoes});
    }
};

pub fn main() !void {
    const config = AppConfig.fromEnv();
    config.imprimir();
}

Dicas e Boas Práticas

  1. Sempre forneça valores padrão: Nunca assuma que uma variável de ambiente existe.

  2. Valide valores numéricos: Use catch ao parsear inteiros de variáveis de ambiente.

  3. Não armazene segredos no código: Use variáveis de ambiente para senhas, tokens e chaves.

  4. Documente as variáveis: Mantenha uma lista das variáveis de ambiente que sua aplicação usa.

Receitas Relacionadas

Tutoriais Relacionados

Continue aprendendo Zig

Explore mais tutoriais e artigos em português para dominar a linguagem Zig.