Configuración: Viper, Env y Archivos de Configuración
Los operadores configuran CLIs y servicios de Go a través de flags, variables de entorno y archivos.
Busca en todas las páginas de la documentación
Los operadores configuran CLIs y servicios de Go a través de flags, variables de entorno y archivos.
Viper (github.com/spf13/viper) centraliza esa capa: valores predeterminados en el código, YAML/TOML/JSON opcional en disco, anulaciones de entorno y enlace de flags desde cobra.
El mismo módulo a menudo potencia tanto cmd/server como cmd/tool, por lo que las reglas de configuración se mantienen consistentes entre los binarios.
La configuración estilo doce factores mantiene los secretos fuera del control de versiones y permite a los contenedores inyectar variables de entorno en tiempo de ejecución.
Viper lee múltiples fuentes y expone GetString, GetInt y similares después de la fusión.
Documenta la precedencia (flags vencen a env, env a archivo, archivo a predeterminados) en README para que los ingenieros de guardia sepan qué valor gana.
Tarjeta de receta de referencia rápida - lista para copiar y pegar.
viper.SetDefault("api.timeout", "30s")
viper.SetConfigName("config")
viper.AddConfigPath(".")
_ = viper.ReadInConfig()
viper.SetEnvPrefix("MYAPP")
viper.AutomaticEnv()
viper.BindPFlags(cmd.Flags())
timeout := viper.GetDuration("api.timeout")Cuándo usar esto:
--config más variables de entorno MYAPP_*.package main
import (
"fmt"
"os"
"strings"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
func main() {
var cfgFile string
root := &cobra.Command{Use: "worker"}
root.PersistentFlags().StringVar(&cfgFile, "config", "", "archivo de configuración")
root.PersistentPreRunE = func(cmd *cobra.Command, args []string) error {
viper.SetDefault("api.url", "http://localhost:8080")
if cfgFile != "" {
viper.SetConfigFile(cfgFile)
} else {
viper.SetConfigName("config")
viper.AddConfigPath(".")
}
_ = viper.ReadInConfig() // archivo opcional
viper.SetEnvPrefix("WORKER")
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
viper.AutomaticEnv()
return viper.BindPFlags(cmd.Flags())
}
root.RunE = func(cmd *cobra.Command, args []string) error {
fmt.Println("api", viper.GetString("api.url"))
return nil
}
if err := root.Execute(); err != nil {
os.Exit(1)
}
}Lo que esto demuestra:
PersistentPreRunE carga la configuración antes de que se ejecute cada subcomando.SetEnvKeyReplacer mapea api.url a WORKER_API_URL.BindPFlags permite que --api.url anule el archivo y el entorno en tiempo de ejecución.ReadInConfig carga el primer archivo encontrado de las rutas de búsqueda.WatchConfig y OnConfigChange habilitan la recarga en caliente (más común en servidores que en CLIs).Unmarshal o UnmarshalKey proyectan la configuración en structs para un acceso seguro a tipos.| Prioridad (alta a baja) | Fuente |
|---|---|
| 1 | Flags explícitos de CLI enlazados con BindPFlags |
| 2 | Variables de entorno (AutomaticEnv) |
| 3 | Archivo de configuración |
| 4 | SetDefault en código |
Documenta cualquier desviación si tu orden de PreRun difiere.
api:
url: https://api.example.com
timeout: 30s
database:
dsn: postgres://localhost:5432/appapi.url en los accesores de viper.config.example.yaml con marcadores de posición seguros.if viper.GetString("api.url") == "" { return err }.mapstructure para configuraciones grandes en lugar de llamadas Get* dispersas.viper.Reset() o usa una instancia de viper nueva a través de viper.New() para evitar la contaminación global.viper.New() por prueba o viper.Reset() en t.Cleanup.API_URL no se mapea a api.url sin reglas de . a _. Solución: SetEnvKeyReplacer(strings.NewReplacer(".", "_")).ReadInConfig ignorado cuando el archivo es opcional. Solución: distingue ConfigFileNotFoundError de fallos de análisis.30s, no 30). Solución: valida al inicio o usa enteros para segundos.viper.AllSettings() vuelca contraseñas. Solución: redacta claves secretas conocidas en impresoras de depuración.| Alternativa | Usar Cuando | No Usar Cuando |
|---|---|---|
| envconfig / caarlos0/env | Solo entorno de struct, sin archivos | Necesitas jerarquías YAML |
| koanf | Cadenas de fusión explícitas | El equipo ya usa viper+cobra |
| os.Getenv manual | Dos variables de entorno en total | Muchas claves anidadas |
| solo flags | Herramientas de CI efímeras | Los operadores necesitan archivos de configuración |
Raramente.
Los controladores de larga ejecución sí; las CLIs de un solo uso leen la configuración una vez al inicio.
Llama a AddConfigPath para /etc/myapp, $HOME/.myapp y . en orden.
El primer archivo legible gana a menos que uses --config explícito.
Sí.
Llama a viper.BindPFlags con un pflag.FlagSet o lee valores después de flag.Parse de la biblioteca estándar.
Carga desde el entorno o administradores de secretos; nunca confirmes DSNs reales.
Valida la presencia al inicio con mensajes de error claros.
Monta YAML como archivos y establece AddConfigPath en el punto de montaje, o proyecta claves en variables de entorno.
Documenta qué claves establece el chart.
Usa viper.New(), establece el entorno con t.Setenv, escribe archivos de configuración temporales y afirma los resultados de GetString.
Evita el viper global en pruebas paralelas.
Sí, con las etiquetas de compilación y las importaciones de analizador apropiadas.
YAML es el más común para la configuración de operadores editada por humanos.
GetInt devuelve 0 para claves faltantes a menos que SetDefault o un archivo proporcionen un valor.
Usa punteros en structs cuando 0 sea válido y ambiguo.
A menudo sí: un paquete internal/config carga viper una vez y expone un struct tipado a ambos binarios.
La sección de observabilidad cubre capas similares para servicios de producción.
Las CLIs reutilizan los mismos nombres de entorno al envolver esos servicios.
Versiones de Stack: Esta página fue escrita para Go 1.26.x (predeterminado Green Tea GC, go fix modernizers - verificar parche en la compilación), chi (última - verificar en la compilación), gin (última - verificar en la compilación), echo (última - verificar en la compilación), google.golang.org/grpc (última - verificar en la compilación), sigs.k8s.io/controller-runtime (última - verificar en la compilación), kubebuilder (última - verificar en la compilación), tinygo (última - verificar objetivos de placa en la compilación), wazero (última - verificar en la compilación) y golangci-lint (última - verificar conjunto de linters en la compilación).
Revisado por Chris St. John·Última actualización: 16 jul 2026