A configuração de uma aplicação é um dos pilares essenciais para garantir flexibilidade e adaptabilidade em diferentes ambientes de execução, como desenvolvimento, teste e produção.
Em Go, gerenciar essas configurações pode ser um desafio, especialmente quando lidamos com múltiplas fontes, como arquivos, variáveis de ambiente e flags de linha de comando.
É aqui que entra o Viper, um package poderoso para gerenciamento de configuração que simplifica esse processo.
O que é o Viper?
O Viper é um package open source desenvolvido para ajudar desenvolvedores Go a gerenciar configurações de maneira eficiente e flexível. Ele permite que sua aplicação leia configurações de várias fontes, como:
- Arquivos de configuração (YAML, JSON, TOML, HCL, etc.)
- Variáveis de ambiente
- Flags de linha de comando
- Key-value stores (como Consul)
- Configurações remotas
Além disso, o Viper oferece recursos como:
- Watcher para detectar alterações em arquivos de configuração e recarregar as configurações dinamicamente
- Suporte a valores padrão para evitar falhas quando uma configuração não é encontrada
- Leitura de configurações em múltiplos formatos de arquivo
Essas funcionalidades tornam o Viper uma solução completa para quem precisa gerenciar configurações em aplicações Go.
Viper na prática
Vamos explorar como o Viper pode ser utilizado em diferentes cenários práticos, iniciando pelo mais básico, a leitura de um arquivo YAML.
1. Lendo configurações de um arquivo YAML
Um dos usos mais comuns do Viper é ler configurações de arquivos YAML. Suponha que temos um arquivo chamado config.yaml com o seguinte conteúdo:
server: port: 8080 host: localhost
Para carregar essas configurações em sua aplicação Go, faça o seguinte:
package main
import (
"fmt"
"github.com/spf13/viper"
)
func main() {
viper.SetConfigName("config")
viper.SetConfigType("yaml")
viper.AddConfigPath(".")
err := viper.ReadInConfig()
if err != nil {
panic(fmt.Errorf("Fatal error config file: %w", err))
}
host := viper.GetString("server.host")
port := viper.GetInt("server.port")
fmt.Printf("Server running on %s:%d\\n", host, port)
}
Explicação:
SetConfigNamedefine o nome do arquivo de configuração (sem a extensão).SetConfigTypeespecifica o tipo do arquivo (neste caso, YAML).AddConfigPathadiciona o caminho onde o arquivo de configuração será procurado.ReadInConfigcarrega o arquivo de configuração.GetStringeGetIntsão usados para acessar os valores das configurações.
2. Utilizando variáveis de ambiente
Em muitos casos, como por exemplo, aplicações executadas como containers no Kubernetes, é comum que as configurações sejam definidas através de variáveis de ambiente.
Por isso, nesse segundo exemplo, vamos configurar o Viper para ler variáveis de ambiente:
package main
import (
"fmt"
"github.com/spf13/viper"
)
func main() {
viper.SetEnvPrefix("app")
viper.BindEnv("port")
viper.BindEnv("host")
host := viper.GetString("host")
port := viper.GetInt("port")
fmt.Printf("Server running on %s:%d\\n", host, port)
}
Explicação:
SetEnvPrefixdefine um prefixo para as variáveis de ambiente.BindEnvvincula as variáveis de ambiente às chaves de configuração.- As variáveis de ambiente esperadas seriam
APP_PORTeAPP_HOST.
3. Usando valores padrão
Valores padrão são úteis para evitar falhas quando uma configuração não é encontrada.
Como podemos ver no exemplo abaixo, no Viper, definir um valor padrão é algo muito simples:
package main
import (
"fmt"
"github.com/spf13/viper"
)
func main() {
viper.SetDefault("server.port", 8080)
viper.SetDefault("server.host", "localhost")
host := viper.GetString("server.host")
port := viper.GetInt("server.port")
fmt.Printf("Server running on %s:%d\\n", host, port)
}
Explicação:
SetDefaultdefine um valor padrão para uma chave de configuração.- Se a chave não for encontrada em outras fontes, o valor padrão será usado.
4. Monitorando alterações no arquivo de configuração
O Viper também pode monitorar alterações em arquivos de configuração e recarregar os valores automaticamente:
package main
import (
"fmt"
"github.com/spf13/viper"
)
func main() {
viper.SetConfigName("config")
viper.SetConfigType("yaml")
viper.AddConfigPath(".")
viper.WatchConfig()
viper.OnConfigChange(func(e fsnotify.Event) {
fmt.Println("Config file changed:", e.Name)
})
err := viper.ReadInConfig()
if err != nil {
panic(fmt.Errorf("Fatal error config file: %w", err))
}
}
Explicação:
WatchConfigativa a observação do arquivo de configuração.OnConfigChangedefine uma função de callback que será executada quando o arquivo for alterado.
Conclusão
O Viper é uma ferramenta poderosa para gerenciar configurações em aplicações Go. Ele simplifica o processo de leitura de configurações de diferentes fontes e ajuda a evitar problemas comuns relacionados à configuração.
Gostou do conteúdo?
- ✅ Inscreva-se na nossa newsletter para receber mais dicas práticas sobre Go, Kubernetes e desenvolvimento de software diretamente no seu e-mail!
- 🚀 Torne-se um assinante pago do blog e tenha acesso a conteúdos exclusivos, como tutoriais avançados, estudos de caso e muito mais!
Faça parte da comunidade!
Receba os melhores conteúdos sobre Go, Kubernetes, arquitetura de software, Cloud e esteja sempre atualizado com as tendências e práticas do mercado.
Livros Recomendados
Abaixo listei alguns dos melhores livros que já li sobre GO.




