Configuração de aplicações em Rust: bibliotecas config e dotenv

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

Configuração de aplicações Rust: bibliotecas config e dotenv



Qualquer aplicação moderna requer um sistema de configuração flexível: configurações de banco de dados, chaves de API, portas do servidor, níveis de log e outros parâmetros. No ecossistema Rust, existem ferramentas poderosas para isso — as crates config e dotenv. Elas permitem combinar configurações de diferentes fontes (arquivos, variáveis de ambiente, argumentos de linha de comando) em uma única estrutura type-safe.



Por que uma biblioteca separada?

Rust é uma linguagem com tipagem estática forte. A simples leitura de strings de std::env::var() leva a várias verificações e transformações manuais. A biblioteca config automatiza esse processo:

  • Suporte a formatos: YAML, JSON, TOML, HJSON, INI, RON
  • Estrutura hierárquica de configurações com possibilidade de sobrescrita
  • Desserialização automática em estruturas personalizadas via serde
  • Combinação de múltiplas fontes com prioridades (arquivo < env < CLI)


Instalação

Adicione ao Cargo.toml:

[dependencies]config = "0.14"serde = { version = "1.0", features = ["derive"] }dotenv = "0.15"


Exemplo básico: leitura de arquivo e env

Vamos criar uma estrutura para a configuração da aplicação:

use serde::Deserialize;use config::Config;

#[derive(Debug, Deserialize)]struct AppConfig { server: ServerConfig, database: DatabaseConfig,}

#[derive(Debug, Deserialize)]struct ServerConfig { host: String, port: u16, workers: u8,}

#[derive(Debug, Deserialize)]struct DatabaseConfig { url: String, pool_size: u32,}

fn main() -> Result<(), config::ConfigError> { // Carrega a configuração let config = Config::builder() .add_source(config::File::with_name("config/default")) .add_source(config::Environment::with_prefix("APP")) .build()?;

let app_config: AppConfig = config.try_deserialize()?; println!("{:#?}", app_config); Ok(())}


Arquivo config/default.toml:

[server]host = "127.0.0.1"port = 8080workers = 4

[database]url = "postgres://localhost/mydb"pool_size = 10


Variáveis de ambiente com o prefixo APP_ sobrescrevem os valores do arquivo. Por exemplo, APP_DATABASE__URL alterará a URL do banco de dados.



Trabalhando com dotenv

Para facilitar o desenvolvimento, é comum usar o arquivo .env. A crate dotenv o carrega nas variáveis de ambiente antes da inicialização do config:

use dotenv::dotenv;

fn main() { dotenv().ok(); // carrega o .env // em seguida, inicialização do config como no exemplo acima}


Conteúdo do .env:

APP_SERVER__PORT=3000APP_DATABASE__POOL_SIZE=20


Cenário avançado: múltiplas fontes

Projetos reais exigem a combinação de configurações de diferentes lugares. O config permite definir uma cadeia de fontes com prioridade:

let config = Config::builder()    // Configurações base (baixa prioridade)    .add_source(config::File::with_name("config/default"))    // Sobrescrita para um ambiente específico    .add_source(config::File::with_name(&format!("config/{}", env::var("APP_ENV").unwrap_or("development"))))    // Variáveis de ambiente (prioridade média)    .add_source(config::Environment::with_prefix("APP"))    // Argumentos de linha de comando (alta prioridade)    .add_source(config::File::from(std::env::args().nth(1).unwrap_or_default()))    .build()?;


Best Practices

  • Use prefixos para variáveis de ambiente, para evitar conflitos com variáveis do sistema

Recommendations