¿Qué es GoDotEnv?
GoDotEnv es una implementación Go de la librería original dotenv de Ruby. Permite separar la configuración del código, siguiendo los principios de las aplicaciones de doce factores, que recomiendan almacenar la configuración en el entorno.
Al utilizar archivos .env, los desarrolladores pueden:
- Mantener información sensible fuera del control de versiones
- Gestionar diferentes configuraciones para entornos distintos (desarrollo, pruebas, producción)
- Compartir configuraciones de forma segura entre miembros del equipo
Instalación
Para instalar GoDotEnv, ejecuta el siguiente comando en tu terminal:
go get github.com/joho/godotenv
Creando un archivo .env
Primero, crea un archivo llamado .env en la raíz de tu proyecto. Este archivo contendrá pares clave-valor con tus variables de entorno.
Ejemplo de archivo .env:
# Configuración de la base de datos
DB_HOST=localhost
DB_PORT=5432
DB_USER=postgres
DB_PASSWORD=secretpassword
DB_NAME=myapp
# Configuración de la API
API_KEY=tu_clave_secreta_api
API_TIMEOUT=30
# Puerto de la aplicación
APP_PORT=8080
Cargando variables de entorno
Ahora, vamos a crear un programa Go simple que cargue estas variables de entorno:
package main
import (
"fmt"
"log"
"github.com/joho/godotenv"
)
func main() {
// Cargar el archivo .env
err := godotenv.Load()
if err != nil {
log.Fatalf("Error cargando el archivo .env: %v", err)
}
fmt.Println("El archivo .env se ha cargado correctamente!")
}
En este código, godotenv.Load() busca un archivo .env en el directorio actual y carga sus variables en el entorno.
Accediendo a las variables
Una vez cargadas las variables, puedes acceder a ellas utilizando la función os.Getenv():
package main
import (
"fmt"
"log"
"os"
"github.com/joho/godotenv"
)
func main() {
// Cargar el archivo .env
err := godotenv.Load()
if err != nil {
log.Fatalf("Error cargando el archivo .env: %v", err)
}
// Acceder a las variables de entorno
dbHost := os.Getenv("DB_HOST")
dbPort := os.Getenv("DB_PORT")
appPort := os.Getenv("APP_PORT")
fmt.Printf("Host de la base de datos: %s\n", dbHost)
fmt.Printf("Puerto de la base de datos: %s\n", dbPort)
fmt.Printf("Puerto de la aplicación: %s\n", appPort)
}
Configuración avanzada
Cargar archivos específicos
Puedes cargar archivos .env específicos pasándolos como argumentos a la función Load():
err := godotenv.Load(".env.development")
Cargar múltiples archivos
También puedes cargar múltiples archivos en orden. Las variables del último archivo tienen prioridad:
err := godotenv.Load(".env.shared", ".env.local")
Cargar desde string
Si necesitas cargar variables desde un string en lugar de un archivo:
envString := `
DB_HOST=localhost
DB_PORT=5432
`
err := godotenv.Unmarshal(envString)
Obtener todas las variables como un mapa
Si necesitas todas las variables como un mapa:
envMap, err := godotenv.Read(".env")
if err != nil {
log.Fatalf("Error leyendo el archivo .env: %v", err)
}
for key, value := range envMap {
fmt.Printf("%s: %s\n", key, value)
}
Mejores prácticas
-
No incluyas archivos .env en el control de versiones:
# Añade a tu .gitignore .env .env.local -
Proporciona un archivo .env.example: Crea un archivo
.env.examplecon la estructura pero sin valores sensibles para compartir con otros desarrolladores. -
Establece variables por defecto: Proporciona valores por defecto cuando sea apropiado.
port := os.Getenv("APP_PORT") if port == "" { port = "8080" // valor por defecto } -
Validación de variables requeridas: Verifica que todas las variables requeridas estén presentes.
requiredEnvs := []string{"DB_HOST", "API_KEY"} for _, env := range requiredEnvs { if os.Getenv(env) == "" { log.Fatalf("Variable de entorno requerida no encontrada: %s", env) } } -
Carga temprana: Carga las variables de entorno al inicio de tu aplicación.
Ejemplo completo
Vamos a crear una aplicación completa que demuestre el uso de GoDotEnv:
package main
import (
"fmt"
"log"
"os"
"strconv"
"github.com/joho/godotenv"
)
// Configuración de la aplicación
type Config struct {
DBHost string
DBPort int
DBUser string
DBPassword string
DBName string
APIKey string
APITimeout int
AppPort int
}
// Cargar la configuración desde variables de entorno
func LoadConfig() (*Config, error) {
// Cargar archivo .env
err := godotenv.Load()
if err != nil {
return nil, fmt.Errorf("error cargando archivo .env: %w", err)
}
// Convertir puerto DB a entero
dbPort, err := strconv.Atoi(os.Getenv("DB_PORT"))
if err != nil {
dbPort = 5432 // valor por defecto
}
// Convertir timeout API a entero
apiTimeout, err := strconv.Atoi(os.Getenv("API_TIMEOUT"))
if err != nil {
apiTimeout = 30 // valor por defecto
}
// Convertir puerto App a entero
appPort, err := strconv.Atoi(os.Getenv("APP_PORT"))
if err != nil {
appPort = 8080 // valor por defecto
}
return &Config{
DBHost: os.Getenv("DB_HOST"),
DBPort: dbPort,
DBUser: os.Getenv("DB_USER"),
DBPassword: os.Getenv("DB_PASSWORD"),
DBName: os.Getenv("DB_NAME"),
APIKey: os.Getenv("API_KEY"),
APITimeout: apiTimeout,
AppPort: appPort,
}, nil
}
// Verificar variables requeridas
func (c *Config) Validate() error {
if c.DBHost == "" {
return fmt.Errorf("variable DB_HOST no definida")
}
if c.DBUser == "" {
return fmt.Errorf("variable DB_USER no definida")
}
if c.APIKey == "" {
return fmt.Errorf("variable API_KEY no definida")
}
return nil
}
func main() {
config, err := LoadConfig()
if err != nil {
log.Fatal(err)
}
// Validar configuración
if err := config.Validate(); err != nil {
log.Fatal(err)
}
// Mostrar configuración cargada
fmt.Println("Configuración cargada correctamente:")
fmt.Printf("DB Host: %s\n", config.DBHost)
fmt.Printf("DB Port: %d\n", config.DBPort)
fmt.Printf("DB User: %s\n", config.DBUser)
fmt.Printf("DB Name: %s\n", config.DBName)
fmt.Printf("API Timeout: %d segundos\n", config.APITimeout)
fmt.Printf("App Port: %d\n", config.AppPort)
// Iniciar aplicación...
fmt.Printf("Iniciando aplicación en el puerto %d...\n", config.AppPort)
}
Para ejecutar este ejemplo, asegúrate de tener un archivo .env en el mismo directorio con las variables mencionadas.
Resolución de problemas comunes
El archivo .env no se carga
- Verifica que el archivo
.envesté en el directorio correcto. Por defecto, godotenv busca en el directorio de trabajo actual. - Asegúrate de que el archivo tenga los permisos adecuados.
Variable no encontrada
- Revisa que la variable esté correctamente definida en el archivo
.env(sin espacios alrededor del=). - Verifica que la carga del archivo haya sido exitosa (comprueba el error devuelto por
godotenv.Load()). - Asegúrate de que estés usando el mismo nombre de variable (las variables de entorno son sensibles a mayúsculas y minúsculas).
Valor incorrecto cargado
- Las variables de entorno son siempre strings. Asegúrate de convertirlas al tipo adecuado antes de usarlas.
- Verifica que no haya comillas innecesarias en el archivo
.env.
Variables duplicadas
- Recuerda que si cargas múltiples archivos, las variables del último archivo sobrescribirán las anteriores.
- Las variables de entorno ya definidas en el sistema no serán sobrescritas por godotenv a menos que uses
godotenv.Overload().
Con este tutorial, ahora deberías tener una buena comprensión de cómo usar GoDotEnv en tus proyectos Go. Esta biblioteca te ayudará a gestionar de forma más eficiente la configuración de tus aplicaciones y a mantener tus credenciales seguras.