獲取Golang環(huán)境變量的三種方式小結(jié)
環(huán)境變量是應(yīng)用軟件參數(shù)配置的最佳方式,可以定義系統(tǒng)級(jí),如開發(fā)、測(cè)試以及生成階段。配置參數(shù)主要有數(shù)據(jù)庫(kù)配置、第三方url等。因此環(huán)境變量對(duì)于開發(fā)和部署應(yīng)用至關(guān)重要。
環(huán)境變量和配置文件
shell 編程中從文件讀變量相對(duì)容易,只需要source包括環(huán)境變量的配置文件,就可以訪問所有這些變量。golang必須依賴一些模塊從文件中讀變量。本文內(nèi)容包括:
- 如何通過文件聲明環(huán)境變量
- 如何從文件讀取環(huán)境變量
- 當(dāng)變量未定義或空,如何設(shè)置缺省值
- 如果從系統(tǒng)讀取環(huán)境變量
- 如何檢查環(huán)境變量被定義或非空
當(dāng)容器化部署應(yīng)用(cloud, Kubernetes, 或Docker)至測(cè)試和生產(chǎn)環(huán)境時(shí),環(huán)境變量角色非常重要,它可以很容易覆蓋缺省配置。golang訪問環(huán)境變量常用方法有三種:
- Viper 包
- godotenv 包
- os 包
我們?cè)谑纠?xiàng)目中創(chuàng)建配置文件app.env文件,用于設(shè)置預(yù)定環(huán)境變量的缺省值。
創(chuàng)建環(huán)境變量配置文件必須遵守一些規(guī)則,否則golang可能不會(huì)識(shí)別變量值:
所有變量必須在單獨(dú)行中聲明
區(qū)分大小寫的變量名應(yīng)該使用大寫命名,單詞應(yīng)該用下劃線分隔,舉例:DB_HOST
變量值跟在變量名稱后面使用等號(hào)分割,舉例:DB_HOST=localhost
變量值不用雙引號(hào),舉例: DB_HOST=”localhost”
注釋不應(yīng)該與變量在一行,舉例:
# depends with database ports mysql,mongodb,postgres etc DB_PORT=5432
舉例,app.env 文件:
# sample app.env # environment can be test,production,testing APP_ENV=development # username DB_USER=postgres # secure password DB_PASS=pass # app version not set APP_VERSION= #listening to any address SERVER_ADDRESS=0.0.0.0:8080 # host value DB_HOST=localhost #depends with database mysql,mongodb,postgres etc DB_PORT=5432
使用Viper包從配置文件中讀環(huán)境變量
這是一個(gè)環(huán)境變量管理工具包,可以從環(huán)境變量或配置文件中讀變量值。通過下面命令安裝包:
go get github.com/spf13/viper
示例1
首先定義結(jié)構(gòu)體,用于全局保存配置文件中的環(huán)境變量。
type Config struct { AppEnv string `mapstructure:"APP_ENV"` DBUser string `mapstructure:"DB_USER"` DBPass string `mapstructure:"DB_PASS"` DBHost string `mapstructure:"DB_HOST"` DBPort string `mapstructure:"DB_PORT"` DBDriver string `mapstructure:"DB_DRIVER"` AppVersion string `mapstructure:"APP_VERSION"` ServerAddress string `mapstructure:"SERVER_ADDRESS"` }
下面定義函數(shù)加載配置文件:
func LoadConfig(path string) (config Config, err error) { // Read file path viper.AddConfigPath(path) // set config file and path viper.SetConfigName("app") viper.SetConfigType("env") // watching changes in app.env viper.AutomaticEnv() // reading the config file err = viper.ReadInConfig() if err != nil { return } err = viper.Unmarshal(&config) return }
完整代碼如下:
package main import ( "fmt" "log" "github.com/spf13/viper" ) // Config stores all configuration of the application. // The values are read by viper from a config file or environment variable. type Config struct { AppEnv string `mapstructure:"APP_ENV"` DBUser string `mapstructure:"DB_USER"` DBPass string `mapstructure:"DB_PASS"` DBHost string `mapstructure:"DB_HOST"` DBPort string `mapstructure:"DB_PORT"` DBDriver string `mapstructure:"DB_DRIVER"` AppVersion string `mapstructure:"APP_VERSION"` ServerAddress string `mapstructure:"SERVER_ADDRESS"` } // LoadConfig reads configuration from file or environment variables. func LoadConfig(path string) (config Config, err error) { // Read file path viper.AddConfigPath(path) // set config file and path viper.SetConfigName("app") viper.SetConfigType("env") // watching changes in app.env viper.AutomaticEnv() // reading the config file err = viper.ReadInConfig() if err != nil { return } err = viper.Unmarshal(&config) return } func main() { // load app.env file data to struct config, err := LoadConfig(".") // handle errors if err != nil { log.Fatalf("can't load environment app.env: %v", err) } fmt.Printf(" -----%s----\n", "Reading Environment variables Using Viper package") fmt.Printf(" %s = %v \n", "Application_Environment", config.AppEnv) // not defined fmt.Printf(" %s = %s \n", "DB_DRIVE", dbDrive) fmt.Printf(" %s = %s \n", "Server_Listening_Address", config.ServerAddress) fmt.Printf(" %s = %s \n", "Database_User_Name", config.DBUser) fmt.Printf(" %s = %s \n", "Database_User_Password", config.DBPass) }
輸出結(jié)果:
$ go run main.go ------Reading Environment variables Using Viper package---------- Application_Environment = development Server_Listening_Address = 0.0.0.0:8080 Database_User_Name = postgres Database_User_Password = pass
示例2
有時(shí)環(huán)境變量可能未設(shè)置,這樣代碼可能會(huì)出錯(cuò),我們可以使用下面方法定義缺省值:
viper.SetDefault:
下面示例代碼定義函數(shù),如果變量未空或未定義,則返回缺省值:
package main import ( "fmt" "github.com/spf13/viper" ) //Function to read an environment or return a default value func getEnvValue(key string, defaultValue string) string { // Get file path viper.SetConfigFile("app.env") //read configs and handle errors err := viper.ReadInConfig() if err != nil { fmt.Println(err) } value := viper.GetString(key) if value != "" { return value } return defaultValue } func main() { // reading environments variable using the viper appEnv := getEnvValue("APP_ENV", "defaultEnvtesting") // not set in our app.env appVersion := getEnvValue("APP_VERSION", "1") dbPass := getEnvValue("DB_PASS", "1234") dbUser := getEnvValue("DB_USER", "goLinux_DB") serverAddress := getEnvValue("SERVER_ADDRESS", "127.0.0.1:8080") fmt.Printf(" ------%s-----\n", "Reading Environment variables Using Viper package") fmt.Printf(" %s = %s \n", "Application_Environment", appEnv) fmt.Printf(" %s = %s \n", "Application_Version", appVersion) fmt.Printf(" %s = %s \n", "Server_Listening_Address", serverAddress) fmt.Printf(" %s = %s \n", "Database_User_Name", dbUser) fmt.Printf(" %s = %s \n", "Database_User_Password", dbPass) }
輸出結(jié)果:
$ go run main.go ---Reading Environment variables Using Viper package-------- Application_Environment = development Application_Version = 1 Server_Listening_Address = 0.0.0.0:8080 Database_User_Name = postgres Database_User_Password = pass
使用GoDotEnv包從配置文件中讀環(huán)境變量
GoDotEnv包功能與viper包類似,但使用godotenv.Load()函數(shù)加載app.env文件,它接收文件名作為輸入,返回應(yīng)用上下文中的值。實(shí)現(xiàn)下面命令安裝包:
go get github.com/joho/godotenv
Load方法可以傳入文件名稱,舉例:godotenv.Load("app.env")
。
有時(shí).env文件位于項(xiàng)目根目錄,則可以直接載入,無需傳入?yún)?shù):godotenv.Load("app.env)
godotenv還支持一次加載多個(gè)配置文件:
_ = godotenv.Load("app.env", "k8s_app.env")
并且還支持YAML文件作為輸入:
// app.YAML APP_ENV: Development SERVER_ADDRESS: 0.0.0.0:8080
下面看一個(gè)完整實(shí)例:
// main.go package main import ( "fmt" "log" "os" "github.com/joho/godotenv" ) // Function to read an environment or return a default value func getEnvValue(key string, defaultValue string) string { if value, ok := os.LookupEnv(key); ok && value != "" { return value } return defaultValue } func main() { // load app.env file err := godotenv.Load("app.env") //handle errors if err != nil { log.Fatalf("can't load environment app.env: %v", err) } // reading environments variable from the app context appEnv := getEnvValue("APP_ENV", "defaultEnvtesting") // not defined in our app.env appVersion := getEnvValue("APP_VERSION", "1") dbPass := getEnvValue("DB_PASS", "1234") // DB_NAME not defined in app env dbName := getEnvValue("DB_NAME", "goLinux_DB") dbUser := getEnvValue("DB_USER", "goLinux_DB") serverAddress := getEnvValue("SERVER_ADDRESS", "127.0.0.1:8080") fmt.Printf(" ----%s---\n", "Reading Environment variables Using GoDotEnv package ") fmt.Printf(" %s = %s \n", "Application_Environment", appEnv) fmt.Printf(" %s = %s \n", "Application_Version", appVersion) fmt.Printf(" %s = %s \n", "Server_Listening_Address", serverAddress) fmt.Printf(" %s = %s \n", "Database_User_Name", dbUser) fmt.Printf(" %s = %s \n", "Database_User_Password", dbPass) fmt.Printf(" %s = %s \n", "Database_Name", dbName) }
輸出結(jié)果:
$ go run main.go -----Reading Environment variables Using GoDotEnv package----- Application_Environment = development Application_Version = 1 Server_Listening_Address = 0.0.0.0:8080 Database_User_Name = postgres Database_User_Password = pass Database_Name = goLinux_DB
使用os包從配置文件中讀環(huán)境變量
使用os.Setenv()設(shè)置環(huán)境變量
os.Setenv(key,value) 接收兩個(gè)輸入?yún)?shù),一個(gè)為key,另一個(gè)是環(huán)境變量值。
語(yǔ)法如下:
err := os.Setenv(key, value) if err != nil { fmt.Printf("error will setting the environment value: %s", err) }
舉例,設(shè)置COLOUR=BLUE:
err := os.Setenv(COLOUR, BLUE) if err != nil { fmt.Printf("error will setting the environment value: %s", err) }
使用os.Getenv()讀系統(tǒng)環(huán)境變量
os.Getenv接收key,舉例,下面代碼獲取環(huán)境變量PATH的值:
// main.go package main import ( "fmt" "os" ) func main() { fmt.Println("supported paths in my shell: ", os.Getenv("PATH")) }
使用os.LookupEnv()讀系統(tǒng)環(huán)境變量
os.Getenv()的缺點(diǎn)是無錯(cuò)誤返回key。對(duì)于需要增加額外檢查是否存在,則需要使用os.LookupEnv(),其返回值中包括布爾變量用于表示key是否存在。舉例:
// main.go package main import ( "fmt" "log" "os" ) func main() { path, ok := os.LookupEnv("PATH123") if !ok { log.Fatalln(path + " variable is not defined") } fmt.Println(path) }
使用os.UnsetEvn()取消設(shè)置環(huán)境變量
os.UnsetEvn() 刪除或取消定義任何系統(tǒng)環(huán)境變量。注意,這只會(huì)暫時(shí)取消當(dāng)前終端的變量設(shè)置。舉例:
// main.go package main import ( "fmt" "os" ) func main() { os.Setenv("MYUSER", "TestUser") // Before unsetting the variable out, _ := os.LookupEnv("MYUSER") fmt.Println("BEFORE: " + out) // Unset the variable os.Unsetenv("MYUSER") // After unsetting the variable out, _ = os.LookupEnv("MYUSER") fmt.Println("AFTER: " + out) }
總結(jié)
到此這篇關(guān)于獲取Golang環(huán)境變量的三種方式小結(jié)的文章就介紹到這了,更多相關(guān)Golang獲取環(huán)境變量?jī)?nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解讀rand.Seed(time.Now().UnixNano())的作用及說明
這篇文章主要介紹了關(guān)于rand.Seed(time.Now().UnixNano())的作用及說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。2023-03-03Windows下CMD執(zhí)行Go出現(xiàn)中文亂碼的解決方法
本文主要介紹了Windows下CMD執(zhí)行Go出現(xiàn)中文亂碼的解決方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02Go語(yǔ)言實(shí)現(xiàn)順序存儲(chǔ)的線性表實(shí)例
這篇文章主要介紹了Go語(yǔ)言實(shí)現(xiàn)順序存儲(chǔ)的線性表的方法,實(shí)例分析了Go語(yǔ)言實(shí)現(xiàn)線性表的定義、插入、刪除元素等的使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-03-03為什么Go里值為nil可以調(diào)用函數(shù)原理分析
這篇文章主要為大家介紹了為什么Go里值為nil可以調(diào)用函數(shù)原理分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08瞅一眼就能學(xué)會(huì)的GO并發(fā)編程使用教程
隨著互聯(lián)網(wǎng)的普及,互聯(lián)網(wǎng)用戶人數(shù)原來越多,這對(duì)系統(tǒng)的性能帶來了巨大的挑戰(zhàn)。這個(gè)時(shí)候就需要并發(fā)編程了,本文為大家整理了詳細(xì)的GO并發(fā)編程使用教程,讓你看完就能學(xué)會(huì)2023-02-02Go實(shí)現(xiàn)短url項(xiàng)目的方法示例
這篇文章主要介紹了Go實(shí)現(xiàn)短url項(xiàng)目的方法示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-03-03使用go語(yǔ)言實(shí)現(xiàn)cors中間件
CORS是一種瀏覽器安全機(jī)制,用于控制在Web應(yīng)用程序中不同源(Origin)之間的資源共享,本文將給大家介紹如何使用go語(yǔ)言實(shí)現(xiàn)cors中間件,文中有詳細(xì)的代碼示例供大家參考,需要的朋友可以參考下2023-09-09Go使用pprof進(jìn)行CPU,內(nèi)存和阻塞情況分析
Go 語(yǔ)言提供了強(qiáng)大的 pprof工具,用于分析 CPU、內(nèi)存、Goroutine 阻塞等性能問題,幫助開發(fā)者優(yōu)化程序,提高運(yùn)行效率,下面我們就來深入了解下pprof 的使用吧2025-03-03