Configuración de aplicaciones en Go (Golang): desde variables de entorno hasta estructuras YAML complejas
La configuración es uno de los aspectos clave de cualquier aplicación en producción. En Go (Golang), el ecosistema ofrece herramientas flexibles y potentes para gestionar ajustes, adaptadas a diferentes escenarios: desde aplicaciones simples de 12 factores hasta microservicios con decenas de parámetros. En este artículo, analizaremos los enfoques principales, las librerías populares y las mejores prácticas para configurar aplicaciones Go.
¿Por qué se necesita una configuración separada?
La codificación rígida de parámetros (hardcode) es un antipatrón. La configuración permite:
- Cambiar el comportamiento de la aplicación sin recompilar;
- Separar ajustes para diferentes entornos (dev/staging/prod);
- Garantizar la seguridad (los secretos no llegan al repositorio);
- Simplificar el despliegue en contenedores y plataformas en la nube.
Enfoque básico: variables de entorno
La librería estándar de Go proporciona la función os.Getenv. Esta es una forma minimalista pero efectiva para proyectos pequeños, que cumple con los principios de la aplicación de 12 factores.
package main
import ( "fmt" "os")
type Config struct { Port string DBHost string DBUser string}
func loadConfig() Config { return Config{ Port: getEnv("APP_PORT", "8080"), DBHost: getEnv("DB_HOST", "localhost"), DBUser: getEnv("DB_USER", "admin"), }}
func getEnv(key, fallback string) string { if value, ok := os.LookupEnv(key); ok { return value } return fallback}
func main() { cfg := loadConfig() fmt.Printf("Server starting on port %s", cfg.Port)}Librería Viper: la «navaja suiza» de la configuración
Viper (de los creadores de Cobra) es la librería más popular para configuración en Go. Soporta múltiples formatos, búsqueda en varias fuentes y jerarquía de ajustes.
Funcionalidades principales de Viper:
- Lectura de YAML, JSON, TOML, HCL, INI, envfile, Java properties;
- Soporte de variables de entorno con prefijos personalizados;
- Establecimiento de valores por defecto;
- Actualización dinámica de configuración (live reload);
- Integración con fuentes remotas (etcd, Consul, Firebase).
Ejemplo de uso de Viper con YAML:
package main
import ( "fmt" "github.com/spf13/viper")
type AppConfig struct { Server ServerConfig `mapstructure:"server"` Database DatabaseConfig `mapstructure:"database"`}
type ServerConfig struct { Port int `mapstructure:"port"` Host string `mapstructure:"host"`}
type DatabaseConfig struct { URL string `mapstructure:"url"` Pool int `mapstructure:"pool"`}
func main() { viper.SetConfigName("config") // nombre del archivo sin extensión viper.SetConfigType("yaml") // formato viper.AddConfigPath(".") // ruta de búsqueda viper.AddConfigPath("./config/")
// Lectura de variables de entorno con prefijo APP_ viper.AutomaticEnv() viper.SetEnvPrefix("APP")
if err := viper.ReadInConfig(); err != nil { panic(fmt.Errorf("fatal error config file: %s", err)) }
var cfg AppConfig if err := viper.Unmarshal(&cfg); err != nil { panic(fmt.Errorf("unable to decode into struct: %s", err)) }
fmt.Printf("Server: %s:%d", cfg.Server.Host, cfg.Server.Port) fmt.Printf("Database URL: %s", cfg.Database.URL)}Ejemplo de archivo config.yaml:
server: port: 8080 host: "0.0.0.0"database: url: "postgres://user:pass@localhost:5432/app" pool: 10Librería envconfig: simplicidad y declaratividad
Si no necesita formatos complejos, sino solo variables de entorno — También en la biblioteca
Trabajo con CSV en Java: bibliotecas OpenCSV y Apache Commons CSV
Criptografía en C++: guía completa de cifrado y hashing
Pruebas en C# (.NET): revisión completa de frameworks y herramientas
Colas de tareas en Java: ExecutorService y ThreadPoolExecutor
PM2 — Monitoreo de aplicaciones JavaScript (Node.js)
Recommendations