Environment Variable Configuration in your Golang Project using Viper
When it comes to creating a production-grade application, using the environment variable in the application is de facto.
Need of the environment variable?
Suppose you have an application with many features and each feature need to access the Database. You configured all the DB information like DBURL
, DBNAME
, USERNAME
and PASSWORD
in each feature
I will talk about the one of major disadvantages of this:
Security Issue:
- You’re entering all the information in the code. Now, all the unauthorized person also have access to the DB.
- If you’re using code versioning tool like
git
then the details of your DB will go public once you push the code.
⚠️ Just don’t forget to include your environment files in the
.gitignore
.
Let’s get into real action :
We will access environment variable in 3 different ways:
1. os Package
Golang provides os
package, an easy way to configure and access the environment variable.
To set the environment variable,os.Setenv(key, value)To get the environment variable,value := os.Getenv(key)
A simple flow of program to access env file using os package:
package main
import (
"fmt"
"os"
)
// use os package to get the env variable which is already set
func envVariable(key string) string {
// set env variable using os package
os.Setenv(key, "dbase")
// return the env variable using os package
return os.Getenv(key)
}
func main() {
// os package
value := envVariable("name")
fmt.Printf("os package: %s = %s \n", "name", value)
}
Run the below command to check.
go run main.go
// Output
os package: name = dbase
2. GoDotEnv Package
The easiest way to load the .env
file is using godotenv
package.
Open the terminal in the project root directory.
Install required package that will be added to go.mod go get github.com/joho/godotenv
godotenv
provides a Load
method to load the env files.
// Load the .env file in the current directory
godotenv.Load()// orgodotenv.Load(".env")
Load method can load multiple env files at once. This also supports
yaml
. For more information check out the documentation.Create a new
.env
file in the project root directory.

usage of accessing environment file from GoDotEnv package:
get_env.go

db_config.go

3. Viper Package
Viper is one of the most popular packages in the golang community. Many Go projects are built using Viper including Hugo, Docker Notary, Mercury.
Viper 🐍 is a complete configuration solution for Go applications including 12-Factor apps. It is designed to work within an application and can handle all types of configuration needs and formats. Reading from JSON, TOML, YAML, HCL, envfile and Java properties config files
For more information read the official documentation of viper
Install
Open the terminal in the project root directory.
go get github.com/spf13/viper
Let’s walk through the code,
viper.SetConfigName("config")
→ Provides the configuration file name.viper.SetConfigPath(".")
→ Provides the path in which viper needs to search for the configuration file.viper.AutomaticEnv()
→ Tells viper to look at the Environment Variables.viper.ReadInConfig()
→ Reads all the configuration variables.viper.Get("variable_name")
→ Returns the value of the "variable name" variable from environment configurations first and if it is not available, it reads from the configuration file.viper.SetDefault("database.dbname", "test_db")
→ Sets a default value to the given variable "database.dbname", if it is not set in the configuration file or environment variables.
Lets get started with configuration part:
Let’s create a new file config.go
inside the util
package.declare a new type Config
struct in this file. This Config
struct will hold all configuration variables of the application that we read from the file or environment variables.

In-order to get the value of the variables and store them in this struct, we need to use the unmarshaling feature of Viper. Viper uses the mapstructure package under the hood for unmarshaling values, so we use the mapstructure
tags to specify the name of each config field.
we must use the exact name of each variable as being declared in the .
env
file

- First, we call
viper.AddConfigPath()
to tell Viper the location of the config file. In this case, the location is given by the input path argument. - Next, we call
viper.SetConfigName()
to tell Viper to look for a config file with a specific name. Our config file isapp.env
, so its name isapp
. - We also tell Viper the type of the config file, which is
env
in this case, by callingviper.SetConfigFile()
and pass inenv
. You can also use JSON, XML or any other format here if you want, just make sure your config file has the correct format and extension. - Now, besides reading configurations from file, we also want viper to read values from environment variables. So we call
viper.AutomaticEnv()
to tell viper to automatically override values that it has read from config file with the values of the corresponding environment variables if they exist. - After that, we call
viper.ReadInConfig()
to start reading config values. Iferror
is not, nil , then we simply return it. - Otherwise, we call
viper.Unmarshal()
to unmarshals the values into the targetconfig
object. And finally, just return theconfig
object and any error if it occurs. - So basically the load config function is completed. Now we can use it in the
main.go
file.
Before that lets set up database connection up :

Then in the main()
function, let’s call util.LoadConfig()
and pass in "."
here, which means the current folder because our config file app.env
is in the same location as this main.go
file.
In my repo, I have set up a database connection where I have called the Loadconfig file in my connection setup.
This is all we have discovered must efficient way of accessing the env file in golang using the viper package.