Configuration with Viper in Go
- Authors
- Name
- Amit Shekhar
- Published on
I am Amit Shekhar, Co-Founder @ Outcome School, I have taught and mentored many developers, and their efforts landed them high-paying tech jobs, helped many tech companies in solving their unique problems, and created many open-source libraries being used by top companies. I am passionate about sharing knowledge through open-source, blogs, and videos.
In this blog, we will learn how to load the configurations from the envfile in Golang using Viper in Go (Golang) projects.
About the viper package: Viper is used to find, load, and unmarshal a configuration file in JSON, TOML, YAML, HCL, INI, envfile, or Java properties formats.
So, let's start learning to use this viper package to load configuration from the envfile in Go.
I will be using the below-mentioned project for the implementation part. The project follows a clean architecture in Go Language. You can find the complete code for loading the configuration using the Viper package mentioned in the blog in the project itself.
Link to the project: Go Backend Clean Architecture.
As a first step, we should install the package:
go get github.com/spf13/viper
We have a .env
file in our project as below:
APP_ENV=development
SERVER_ADDRESS=:8080
PORT=8080
CONTEXT_TIMEOUT=2
DB_HOST=localhost
DB_PORT=27017
DB_USER=
DB_PASS=
DB_NAME=go-backend-clean-architecture-db
ACCESS_TOKEN_EXPIRY_HOUR = 2
REFRESH_TOKEN_EXPIRY_HOUR = 168
ACCESS_TOKEN_SECRET=access_token_secret
REFRESH_TOKEN_SECRET=refresh_token_secret
And, we want to load the configuration from this .env
file.
Now, we have to create a struct Env
in the env.go
file as below:
type Env struct {
AppEnv string `mapstructure:"APP_ENV"`
ServerAddress string `mapstructure:"SERVER_ADDRESS"`
ContextTimeout int `mapstructure:"CONTEXT_TIMEOUT"`
DBHost string `mapstructure:"DB_HOST"`
DBPort string `mapstructure:"DB_PORT"`
DBUser string `mapstructure:"DB_USER"`
DBPass string `mapstructure:"DB_PASS"`
DBName string `mapstructure:"DB_NAME"`
AccessTokenExpiryHour int `mapstructure:"ACCESS_TOKEN_EXPIRY_HOUR"`
RefreshTokenExpiryHour int `mapstructure:"REFRESH_TOKEN_EXPIRY_HOUR"`
AccessTokenSecret string `mapstructure:"ACCESS_TOKEN_SECRET"`
RefreshTokenSecret string `mapstructure:"REFRESH_TOKEN_SECRET"`
}
Then, create a function in the same env.go
file to load the .env
file and unmarshal it into the above created Env
struct.
func NewEnv() *Env {
env := Env{}
viper.SetConfigFile(".env")
err := viper.ReadInConfig()
if err != nil {
log.Fatal("Can't find the file .env : ", err)
}
err = viper.Unmarshal(&env)
if err != nil {
log.Fatal("Environment can't be loaded: ", err)
}
if env.AppEnv == "development" {
log.Println("The App is running in development env")
}
return &env
}
Here, we can notice that we have provided the file .env
to the viper using the SetConfigFile
method, then read and finally unmarshal it into the Env
struct.
The complete env.go
file will be as below:
package bootstrap
import (
"log"
"github.com/spf13/viper"
)
type Env struct {
AppEnv string `mapstructure:"APP_ENV"`
ServerAddress string `mapstructure:"SERVER_ADDRESS"`
ContextTimeout int `mapstructure:"CONTEXT_TIMEOUT"`
DBHost string `mapstructure:"DB_HOST"`
DBPort string `mapstructure:"DB_PORT"`
DBUser string `mapstructure:"DB_USER"`
DBPass string `mapstructure:"DB_PASS"`
DBName string `mapstructure:"DB_NAME"`
AccessTokenExpiryHour int `mapstructure:"ACCESS_TOKEN_EXPIRY_HOUR"`
RefreshTokenExpiryHour int `mapstructure:"REFRESH_TOKEN_EXPIRY_HOUR"`
AccessTokenSecret string `mapstructure:"ACCESS_TOKEN_SECRET"`
RefreshTokenSecret string `mapstructure:"REFRESH_TOKEN_SECRET"`
}
func NewEnv() *Env {
env := Env{}
viper.SetConfigFile(".env")
err := viper.ReadInConfig()
if err != nil {
log.Fatal("Can't find the file .env : ", err)
}
err = viper.Unmarshal(&env)
if err != nil {
log.Fatal("Environment can't be loaded: ", err)
}
if env.AppEnv == "development" {
log.Println("The App is running in development env")
}
return &env
}
After that, we can just have the Env
as below:
env := NewEnv()
Finally, we can just access the configuration as below:
dbName := env.DBName
secret := env.AccessTokenSecret
So, this way we are able to access the configuration values.
I will highly recommend going through the project and checking the usage of viper to load the configuration.
Link to the project: Go Backend Clean Architecture.
This is how we can load the configurations from the envfile in Golang using Viper in Go (Golang) projects.
That's it for now.
Thanks
Amit Shekhar
Co-Founder @ Outcome School
You can connect with me on:
Follow Outcome School on: