Guide pratique des variables d'environnement dans Go

Bonjour, Habr! Je vous présente la traduction de l'article Un guide pratique des variables d'environnement dans Go par Enda Phelan.

Les variables d'environnement sont le meilleur moyen de stocker les configurations d'application, car elles peuvent être définies au niveau du système. C'est l'un des principes de la méthodologie de l' application à douze facteurs , il vous permet de séparer les applications du système dans lequel elles s'exécutent (la configuration peut varier considérablement entre les déploiements, le code ne doit pas différer).

Utilisation de variables d'environnement


Tout ce qui est nécessaire pour interagir avec les variables d'environnement se trouve dans la bibliothèque standard os . Voici comment obtenir la valeur de la variable d'environnement PATH:

package main import ( "fmt" "os" ) func main() { // Store the PATH environment variable in a variable path, exists := os.LookupEnv("PATH") if exists { // Print the value of the environment variable fmt.Print(path) } } 

Et donc - définissez la valeur de la variable:

 package main import ( "fmt" "os" ) func main() { // Set the USERNAME environment variable to "MattDaemon" os.Setenv("USERNAME", "MattDaemon") // Get the USERNAME environment variable username := os.Getenv("USERNAME") // Prints out username environment variable fmt.Print(username) } 

Chargement de variables d'environnement à partir d'un fichier .env


Sur une machine de développement, où de nombreux projets sont lancés immédiatement, le stockage des paramètres dans des environnements variables n'est pas toujours pratique; il serait plus logique de les répartir entre projets à l'aide de fichiers env. Vous pouvez le faire, par exemple, en utilisant godotenv - c'est le dotenv porté sur la bibliothèque Go Ruby. Il vous permet de définir les variables d'environnement nécessaires à l'application à partir du fichier .env.

Pour installer le package, exécutez:

 go get github.com/joho/godotenv 

Ajoutez les paramètres au fichier .env à la racine du projet:

 GITHUB_USERNAME=craicoverflow GITHUB_API_KEY=TCtQrZizM1xeo1v92lsVfLOHDsF7TfT5lMvwSno 

Vous pouvez maintenant utiliser ces valeurs dans l'application:

 package main import ( "log" "github.com/joho/godotenv" "fmt" "os" ) // init is invoked before main() func init() { // loads values from .env into the system if err := godotenv.Load(); err != nil { log.Print("No .env file found") } } func main() { // Get the GITHUB_USERNAME environment variable githubUsername, exists := os.LookupEnv("GITHUB_USERNAME") if exists { fmt.Println(githubUsername) } // Get the GITHUB_API_KEY environment variable githubAPIKey, exists := os.LookupEnv("GITHUB_API_KEY") if exists { fmt.Println(githubAPIKey) } } 

Il est important de se rappeler que si la valeur de la variable d'environnement est définie au niveau du système, Go utilisera cette valeur au lieu de celle spécifiée dans le fichier env.

Enveloppez les variables d'environnement dans le module de configuration


C’est bien, bien sûr, d’avoir directement accès aux variables d’environnement, comme illustré ci-dessus, mais maintenir une telle solution semble plutôt problématique. Le nom de la variable est une chaîne, et si elle change, imaginez un casse-tête qui entraînera le processus de mise à jour des références de variable dans l'application.

Pour résoudre ce problème, nous allons créer un module de configuration pour travailler avec les variables d'environnement de manière plus centralisée et prise en charge.

Voici un module de configuration simple qui renvoie les paramètres de configuration dans la structure de configuration (nous définissons également les valeurs par défaut des paramètres au cas où il n'y aurait pas de variable d'environnement dans le système):

 package config import ( "os" ) type GitHubConfig struct { Username string APIKey string } type Config struct { GitHub GitHubConfig } // New returns a new Config struct func New() *Config { return &Config{ GitHub: GitHubConfig{ Username: getEnv("GITHUB_USERNAME", ""), APIKey: getEnv("GITHUB_API_KEY", ""), }, } } // Simple helper function to read an environment or return a default value func getEnv(key string, defaultVal string) string { if value, exists := os.LookupEnv(key); exists { return value } return defaultVal } 

Ensuite, ajoutez les types à la structure Config , car la solution existante ne prend en charge que les types de chaîne, ce qui n'est pas très raisonnable pour les grandes applications.

Créez des gestionnaires pour les types bool, slice et integer:

 package config import ( "os" "strconv" "strings" ) type GitHubConfig struct { Username string APIKey string } type Config struct { GitHub GitHubConfig DebugMode bool UserRoles []string MaxUsers int } // New returns a new Config struct func New() *Config { return &Config{ GitHub: GitHubConfig{ Username: getEnv("GITHUB_USERNAME", ""), APIKey: getEnv("GITHUB_API_KEY", ""), }, DebugMode: getEnvAsBool("DEBUG_MODE", true), UserRoles: getEnvAsSlice("USER_ROLES", []string{"admin"}, ","), MaxUsers: getEnvAsInt("MAX_USERS", 1), } } // Simple helper function to read an environment or return a default value func getEnv(key string, defaultVal string) string { if value, exists := os.LookupEnv(key); exists { return value } return defaultVal } // Simple helper function to read an environment variable into integer or return a default value func getEnvAsInt(name string, defaultVal int) int { valueStr := getEnv(name, "") if value, err := strconv.Atoi(valueStr); err == nil { return value } return defaultVal } // Helper to read an environment variable into a bool or return default value func getEnvAsBool(name string, defaultVal bool) bool { valStr := getEnv(name, "") if val, err := strconv.ParseBool(valStr); err == nil { return val } return defaultVal } // Helper to read an environment variable into a string slice or return default value func getEnvAsSlice(name string, defaultVal []string, sep string) []string { valStr := getEnv(name, "") if valStr == "" { return defaultVal } val := strings.Split(valStr, sep) return val } 

Ajoutez de nouvelles variables d'environnement à notre fichier env:

 GITHUB_USERNAME=craicoverflow GITHUB_API_KEY=TCtQrZizM1xeo1v92lsVfLOHDsF7TfT5lMvwSno MAX_USERS=10 USER_ROLES=admin,super_admin,guest DEBUG_MODE=false 

Vous pouvez maintenant les utiliser n'importe où dans l'application:

 package main import ( "fmt" "log" "github.com/craicoverflow/go-environment-variables-example/config" "github.com/joho/godotenv" ) // init is invoked before main() func init() { // loads values from .env into the system if err := godotenv.Load(); err != nil { log.Print("No .env file found") } } func main() { conf := config.New() // Print out environment variables fmt.Println(conf.GitHub.Username) fmt.Println(conf.GitHub.APIKey) fmt.Println(conf.DebugMode) fmt.Println(conf.MaxUsers) // Print out each role for _, role := range conf.UserRoles { fmt.Println(role) } } 

C'est fait!


Oui, il existe des packages qui offrent une solution clé en main pour configurer votre application, mais combien sont-ils nécessaires s'il est si facile de le faire vous-même?

Et comment gérez-vous la configuration dans votre application?

Source: https://habr.com/ru/post/fr446468/


All Articles