Panduan Praktis untuk Variabel Lingkungan dalam Go

Halo, Habr! Saya sajikan kepada Anda terjemahan artikel Panduan yang tidak masuk akal untuk variabel lingkungan di Go by Enda Phelan.

Variabel lingkungan adalah cara terbaik untuk menyimpan konfigurasi aplikasi, karena mereka dapat diatur pada tingkat sistem. Ini adalah salah satu prinsip dari metodologi App Dua Belas-Faktor , memungkinkan Anda untuk memisahkan aplikasi dari sistem di mana mereka berjalan (konfigurasi dapat bervariasi secara signifikan antara penyebaran, kode tidak boleh berbeda).

Menggunakan variabel lingkungan


Semua yang diperlukan untuk berinteraksi dengan variabel lingkungan ada di pustaka standar os . Ini adalah cara mendapatkan nilai dari variabel lingkungan 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) } } 

Dan - atur nilai variabel:

 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) } 

Memuat variabel lingkungan dari file .env


Pada mesin pengembangan, di mana banyak proyek diluncurkan segera, menyimpan parameter di lingkungan variabel tidak selalu nyaman; akan lebih logis untuk membaginya antara proyek menggunakan file env. Anda dapat melakukan ini, misalnya, menggunakan godotenv - ini adalah dotenv porting ke perpustakaan Go Ruby. Ini memungkinkan Anda untuk mengatur variabel lingkungan yang diperlukan untuk aplikasi dari file .env.

Untuk menginstal paket, jalankan:

 go get github.com/joho/godotenv 

Tambahkan pengaturan ke file .env di root proyek:

 GITHUB_USERNAME=craicoverflow GITHUB_API_KEY=TCtQrZizM1xeo1v92lsVfLOHDsF7TfT5lMvwSno 

Sekarang Anda dapat menggunakan nilai-nilai ini dalam aplikasi:

 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) } } 

Penting untuk diingat bahwa jika nilai variabel lingkungan diatur pada tingkat sistem, Go akan menggunakan nilai ini alih-alih yang ditentukan dalam file env.

Bungkus variabel lingkungan dalam modul konfigurasi


Memang menyenangkan, tentu saja, memiliki akses ke variabel lingkungan secara langsung, seperti yang ditunjukkan di atas, tetapi mempertahankan solusi seperti itu tampaknya agak bermasalah. Nama variabel adalah string, dan jika itu berubah, maka bayangkan sakit kepala yang akan mengakibatkan proses memperbarui referensi variabel di seluruh aplikasi.

Untuk mengatasi masalah ini, kami akan membuat modul konfigurasi untuk bekerja dengan variabel lingkungan dengan cara yang lebih terpusat dan didukung.

Berikut ini adalah modul konfigurasi sederhana yang mengembalikan parameter konfigurasi dalam struktur Konfigurasi (kami juga menetapkan nilai parameter default jika tidak ada variabel lingkungan dalam sistem):

 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 } 

Selanjutnya, tambahkan tipe ke struktur Config , karena solusi yang ada hanya mendukung tipe string, yang tidak terlalu masuk akal untuk aplikasi besar.

Buat penangan untuk tipe bool, slice dan 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 } 

Tambahkan variabel lingkungan baru ke file env kami:

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

Sekarang Anda dapat menggunakannya di mana saja di aplikasi:

 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) } } 

Selesai!


Ya, ada paket yang menawarkan solusi turnkey untuk mengkonfigurasi aplikasi Anda, tetapi berapa banyak yang dibutuhkan jika sangat mudah melakukannya sendiri?

Dan bagaimana Anda mengelola konfigurasi di aplikasi Anda?

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


All Articles