Configuration with Viper in Go
Tags: go, backend
Published: 2023-01-16 13:46:14

---
title: Configuration with Viper in Go
published: true
description: In this blog, we will learn how to load the configurations from the envfile in Golang using Viper in Go (Golang) projects.
tags: go, golang, backend
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vifsqa8lkdccjokxy62t.png
canonical_url: https://outcomeschool.com/blog/configuration-with-viper-in-go
---

Hi, I am Amit Shekhar, Co-Founder @ [Outcome School](https://outcomeschool.com) • IIT 2010-14 • 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.

**This article was originally published at [Outcome School](https://outcomeschool.com/blog/configuration-with-viper-in-go).**

**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](https://github.com/amitshekhariitbhu/go-backend-clean-architecture).

As a first step, we should install the package:

```bash
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:

```go
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.

```go
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:

```go
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:

```go
env := NewEnv()
```

Finally, we can just access the configuration as below:

```go
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](https://github.com/amitshekhariitbhu/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](https://outcomeschool.com)

You can connect with me on:

- [Twitter](https://twitter.com/amitiitbhu)
- [YouTube](https://www.youtube.com/@amitshekhar)
- [LinkedIn](https://www.linkedin.com/in/amit-shekhar-iitbhu)
- [GitHub](https://github.com/amitshekhariitbhu)

[**Read all of our blogs here.**](https://outcomeschool.com/blog)