Environment variables are the best way to configure software parameters and can define the system level, such as development, testing, and generation stages. The configuration parameters mainly include database configuration, third-party url, etc. Therefore, environment variables are crucial for the development and deployment of applications.
Environment variables and configuration files
It is relatively easy to read variables from files in shell programming. You only need to source the configuration file that includes the environment variables to access all of these variables. golang must rely on some modules to read variables from files. The content of this article includes:
- How to declare environment variables through files
- How to read environment variables from a file
- How to set the default value when the variable is undefined or empty
- If you read environment variables from the system
- How to check if environment variables are defined or not empty
When deploying applications (cloud, Kubernetes, or Docker) in containerized to test and production environments, the environment variable role is very important, and it can easily override the default configuration. There are three common methods for golang to access environment variables:
- Viper Package
- godotenv package
- os package
We create a configuration file in the sample project to set the default values for predetermined environment variables.
There are some rules to follow when creating an environment variable configuration file, otherwise golang may not recognize the variable value:
All variables must be declared in separate lines
Case-sensitive variable names should be named in capital, and words should be separated by underscores. Example: DB_HOST
The variable value is divided by an equal sign after the variable name. For example: DB_HOST=localhost
Variable values do not use double quotes, for example: DB_HOST="localhost"
Comments should not be on the same line as variables, for example:
# depends with database ports mysql,mongodb,postgres etc DB_PORT=5432
For example, file:
# sample # 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
Read environment variables from configuration files using Viper package
This is an environment variable management toolkit that allows you to read variable values from environment variables or configuration files. Install the package through the following command:
go get /spf13/viper
Example 1
First, define the structure to save environment variables in the configuration file globally.
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"` }
The following defines the function loading configuration file:
func LoadConfig(path string) (config Config, err error) { // Read file path (path) // set config file and path ("app") ("env") // watching changes in () // reading the config file err = () if err != nil { return } err = (&config) return }
The complete code is as follows:
package main import ( "fmt" "log" "/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 (path) // set config file and path ("app") ("env") // watching changes in () // reading the config file err = () if err != nil { return } err = (&config) return } func main() { // load file data to struct config, err := LoadConfig(".") // handle errors if err != nil { ("can't load environment : %v", err) } (" -----%s----\n", "Reading Environment variables Using Viper package") (" %s = %v \n", "Application_Environment", ) // not defined (" %s = %s \n", "DB_DRIVE", dbDrive) (" %s = %s \n", "Server_Listening_Address", ) (" %s = %s \n", "Database_User_Name", ) (" %s = %s \n", "Database_User_Password", ) }
Output result:
$ go run ------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
Example 2
Sometimes the environment variable may not be set, so the code may error. We can use the following method to define the default value:
:
The following example code defines a function, which returns the default value if the variable is not empty or undefined:
package main import ( "fmt" "/spf13/viper" ) //Function to read an environment or return a default value func getEnvValue(key string, defaultValue string) string { // Get file path ("") //read configs and handle errors err := () if err != nil { (err) } value := (key) if value != "" { return value } return defaultValue } func main() { // reading environments variable using the viper appEnv := getEnvValue("APP_ENV", "defaultEnvtesting") // not set in our 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") (" ------%s-----\n", "Reading Environment variables Using Viper package") (" %s = %s \n", "Application_Environment", appEnv) (" %s = %s \n", "Application_Version", appVersion) (" %s = %s \n", "Server_Listening_Address", serverAddress) (" %s = %s \n", "Database_User_Name", dbUser) (" %s = %s \n", "Database_User_Password", dbPass) }
Output result:
$ go run ---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
Read environment variables from configuration files using GoDotEnv package
The GoDotEnv package function is similar to the viper package, but uses the() function to load the file, which receives the file name as input, returning the value in the application context. Implement the following command to install the package:
go get /joho/godotenv
The Load method can pass in the file name, for example:("")
。
Sometimes the .env file is located in the project root directory, and it can be loaded directly without passing in parameters:(")
godotenv also supports loading multiple configuration files at once:
_ = ("", "k8s_app.env")
It also supports YAML files as input:
// APP_ENV: Development SERVER_ADDRESS: 0.0.0.0:8080
Here is a complete example:
// package main import ( "fmt" "log" "os" "/joho/godotenv" ) // Function to read an environment or return a default value func getEnvValue(key string, defaultValue string) string { if value, ok := (key); ok && value != "" { return value } return defaultValue } func main() { // load file err := ("") //handle errors if err != nil { ("can't load environment : %v", err) } // reading environments variable from the app context appEnv := getEnvValue("APP_ENV", "defaultEnvtesting") // not defined in our 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") (" ----%s---\n", "Reading Environment variables Using GoDotEnv package ") (" %s = %s \n", "Application_Environment", appEnv) (" %s = %s \n", "Application_Version", appVersion) (" %s = %s \n", "Server_Listening_Address", serverAddress) (" %s = %s \n", "Database_User_Name", dbUser) (" %s = %s \n", "Database_User_Password", dbPass) (" %s = %s \n", "Database_Name", dbName) }
Output result:
$ go run -----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
Read environment variables from configuration files using os package
Set environment variables using ()
(key,value) Receives two input parameters, one is key and the other is the environment variable value.
The syntax is as follows:
err := (key, value) if err != nil { ("error will setting the environment value: %s", err) }
For example, set COLOUR=BLUE:
err := (COLOUR, BLUE) if err != nil { ("error will setting the environment value: %s", err) }
Read system environment variables using ()
Receive key, for example, the following code obtains the value of the environment variable PATH:
// package main import ( "fmt" "os" ) func main() { ("supported paths in my shell: ", ("PATH")) }
Read system environment variables using ()
The disadvantage of () is that there is no error to return the key. For additional checks that need to be added, you need to use(), which includes a Boolean variable to indicate whether the key exists. For example:
// package main import ( "fmt" "log" "os" ) func main() { path, ok := ("PATH123") if !ok { (path + " variable is not defined") } (path) }
Use() to unset environment variables
() Delete or undefine any system environment variables. Note that this will only temporarily cancel the variable settings of the current terminal. For example:
// package main import ( "fmt" "os" ) func main() { ("MYUSER", "TestUser") // Before unsetting the variable out, _ := ("MYUSER") ("BEFORE: " + out) // Unset the variable ("MYUSER") // After unsetting the variable out, _ = ("MYUSER") ("AFTER: " + out) }
Summarize
This is the end of this article about the three ways to obtain Golang environment variables. For more relevant content on Golang to obtain environment variables, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!