How to read env variables in Golang using viper
Tags: go, viper, beginners, tutorial
Published: 2022-05-31 04:55:46

Using Env variables are one of the ways to secure your app's secrets and it is widely used in almost all the applications.

You have to be aware of such production practices to secure your application!

In this blog we will read environment variables (store our secret keys securely) using **viper** package from GO.

I have kept this post simple yet informative so, Let's jump right into it!

## Project Setup
Here we create the project structure for this tutorial.

I suggest you to glance through this section even if you already have a project ready. This will help you understand this tutorial better.

**1. Start a new GO project**

_Go to go workspace_
```
cd $GOPATH
```
_Create a project and go to the project_
```
mkdir read-env-var
cd read-env-var
```

**2. Initialize the project**
```
go mod init github.com/YOUR_USERNAME/read-env-var
```
**3. Let's create the project structure**
```
mkdir -p cmd pkg/common/envs pkg/common/config
```
**4. Create files**
```
touch Makefile cmd/main.go pkg/common/envs/.env pkg/common/config/config.go
```
Finally, your project structure should look like this,

![Project structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lvi9efs0zg8aa28uf66a.png)

## Environment Variables
First, we need to add some environment variables where we store the application port and other secrets.

Let’s add code to pkg/common/envs/.env
```
PORT=:3000
DB_URL=postgres://DB_USER:DB_PASSWORD@DB_HOST:DB_PORT/go_api_medium
API_KEY=<YOUR_API_KEY_HERE>
```

## Install viper
Viper is the package, that we will be using to read the env variable and use it in our project

```
go get github.com/spf13/viper
```
## Viper Configuration
Let’s add code to pkg/common/config/config.go

```
package config

import "github.com/spf13/viper"

type Config struct {
    Port  string `mapstructure:"PORT"`
    DBUrl string `mapstructure:"DB_URL"`
}

func LoadConfig() (c Config, err error) {
    viper.AddConfigPath("./pkg/common/config/envs")
    viper.SetConfigName("dev")
    viper.SetConfigType("env")

    viper.AutomaticEnv()

    err = viper.ReadInConfig()

    if err != nil {
        return
    }

    err = viper.Unmarshal(&c)

    return
}
```

## Main file
We will initialize viper to handle our env variables

Let’s add code to cmd/main.go
```
package main

import (
    "fmt"
    "github.com/spf13/viper"
)

func main() {
    viper.SetConfigFile("./pkg/common/envs/.env")
    viper.ReadInConfig()

    // add env variables as needed
    port := viper.Get("PORT").(string)
    dbUrl := viper.Get("DB_URL").(string)

    fmt.Println(port, dbUrl)
}
```
## Run the code
Let add our script in MakeFile
```
server:
     go run cmd/main.go
```
and then, run `make server` script in terminal

(or)

Directly run command in terminal
```
go run cmd/main.go
```

Output:

![Output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v4d4sv7gdc66nlk2rdaf.png)

That's it folks. To summarise, we

1. Created a Go project
2. Added env variables
3. Installed viper package
4. Added viper configuration
5. Initialised viper in main.go file

In the [next tutorial](https://dev.to/devniklesh/crud-api-with-go-gin-framework-production-ready-52jd), we will extend this project to add CRUD API using Gin framework. Make sure to follow and like this tutorial. Thanks for being here!

Please share it with your friends & colleagues.