Configuração com viper & envconfig
Serviços e CLIs precisam de configuração que muda por ambiente sem recompilação.
Busque em todas as páginas da documentação
Serviços e CLIs precisam de configuração que muda por ambiente sem recompilação.
spf13/viper mescla arquivos, flags e variáveis de ambiente com regras de precedência; kelseyhightower/envconfig mapeia variáveis de ambiente diretamente para structs tipados para binários menores.
Cartão de receita de referência rápida - pronto para copiar e colar.
viper.SetConfigName("config")
viper.SetConfigType("yaml")
viper.AddConfigPath(".")
viper.AutomaticEnv()
viper.SetDefault("http.port", 8080)
_ = viper.ReadInConfig()
port := viper.GetInt("http.port")type Config struct {
Port int `envconfig:"PORT" default:"8080"`
DSN string `envconfig:"DATABASE_URL" required:"true"`
}
var cfg Config
envconfig.Process("", &cfg)Quando usar isso:
os.Getenv ad hoc espalhado por pacotespackage main
import (
"fmt"
"log"
"strings"
"github.com/spf13/viper"
)
type AppConfig struct {
HTTPPort int
LogLevel string
DSN string
}
func loadViper() AppConfig {
viper.SetConfigName("config")
viper.SetConfigType("yaml")
viper.AddConfigPath(".")
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
viper.AutomaticEnv()
viper.SetDefault("http.port", 8080)
viper.SetDefault("log.level", "info")
if err := viper.ReadInConfig(); err != nil {
log.Printf("nenhum arquivo de configuração: %v", err)
}
return AppConfig{
HTTPPort: viper.GetInt("http.port"),
LogLevel: viper.GetString("log.level"),
DSN: viper.GetString("database.dsn"),
}
}
func main() {
cfg := loadViper()
if cfg.DSN == "" {
log.Fatal("database.dsn ou DATABASE_DSN é obrigatório")
}
fmt.Printf("port=%d level=%s\n", cfg.HTTPPort, cfg.LogLevel)
}O que isso demonstra:
AutomaticEnv e replacer de chavesmainAppConfig tipado separado da API stringly do viperrequired ausentes.fsnotify (viper) ou reinício do processo (modelo de operação mais simples).main ou em um pacote config; pacotes de domínio recebem structs tipados, não chamadas globais do viper.| Fonte | Uso Típico | Força de Substituição |
|---|---|---|
Set explícito no código | Testes | Mais alta quando usada |
Flags (viper.BindPFlags) | Substituições de CLI | Alta |
| Ambiente | Segredos K8s, 12-factor | Alta |
| Arquivo de configuração | Padrões por ambiente | Média |
SetDefault | Fallbacks seguros | Baixa |
| Tag | Efeito |
|---|---|
envconfig:"PORT" | Nome da variável de ambiente (com prefixo opcional) |
required:"true" | O processo falha se não estiver definido |
default:"8080" | Valor quando o env está ausente |
split_words:"true" | HTTP_PORT mapeia para HTTPPort |
// Prefira desmaterializar em um struct assim que as chaves do viper se estabilizarem
var cfg AppConfig
if err := viper.Unmarshal(&cfg); err != nil {
log.Fatal(err)
}info.viper.GetString escondem dependências. Correção: carregar em main, passar structs AppConfig.http.port vs HTTP_PORT falha silenciosamente sem SetEnvKeyReplacer. Correção: documentar nomes de env em tabelas Helm e README.GetString. Correção: validar com if cfg.DSN == "" explícito ou required do envconfig.viper.WatchConfig recarrega no meio da requisição. Correção: reiniciar pods ou controlar o reload com troca atômica de ponteiro mais drain.flag.Parse perde substituições de CLI. Correção: analisar flags primeiro, depois vincular com viper.BindPFlags.| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
flag + os.Getenv apenas | Duas variáveis de ambiente e uma flag de porta | Dezenas de chaves em vários arquivos |
caarlos0/env | Tags de struct sem a antiguidade do envconfig | Você já padronizou o envconfig |
koanf | Camadas de mesclagem explícitas sem globais do viper | Equipe conhece viper e quer uma ferramenta |
| Apenas valores Helm | Configuração nunca local | Desenvolvedores precisam de go run offline |
Comece com envconfig quando toda a configuração vier de env e Secrets do Kubernetes.
Adicione viper quando precisar de padrões YAML para desenvolvimento local e flags de recursos baseadas em arquivos.
Defina variáveis de ambiente em t.Setenv, escreva arquivos YAML temporários ou construa literais AppConfig em testes sem tocar no viper global, quando possível.
Frequentemente sim para structs AppConfig compartilhados; CLIs podem adicionar vinculações pflag onde os serviços dependem apenas de env.
Essa página cobre padrões de flags e env de forma ampla; esta página compara especificamente as bibliotecas viper e envconfig.
Sim - carregue padrões de arquivo com viper, depois sobreponha com envconfig para segredos - mas prefira um carregador para evitar confusão de precedência.
Desmaterialize em structs e execute go-playground/validator ou verificações feitas à mão em portas, URLs e durações.
Gere uma tabela a partir de tags de struct no README, duplique em comentários do values.yaml do Helm e falhe na inicialização com mensagens de erro acionáveis.
Para CLIs de binário único com três flags, a biblioteca padrão flag é mais simples e evita uma dependência.
Armazene chaves de flag em arquivos viper ou em um provedor remoto; mantenha padrões seguros quando o provedor for inacessível.
Sim - um pacote é responsável pelo carregamento, validação e String() redigido para logs.
Versões da Pilha: Esta página foi escrita para Go 1.26.x (padrão GC Green Tea, go fix modernizers - verifique o patch na compilação), chi (mais recente - verifique na compilação), gin (mais recente - verifique na compilação), echo (mais recente - verifique na compilação), google.golang.org/grpc (mais recente - verifique na compilação), sigs.k8s.io/controller-runtime (mais recente - verifique na compilação), kubebuilder (mais recente - verifique na compilação), tinygo (mais recente - verifique os alvos de placa na compilação), wazero (mais recente - verifique na compilação) e golangci-lint (mais recente - verifique o conjunto de linters na compilação).
Revisado por Chris St. John·Última atualização: 19 de jul. de 2026