Select Page

Introduction to Viper in Go and Golang

Manoj Debnath
Published: September 22, 2022

Go Programming ``

In Go, there are many packages to handle application configuration. The viper package is most popular among them in providing a complete configuration solution of an application. It supports numerous configuration file formats such as JSON, YAML, TOML, HCL and Java properties format. This programming tutorial introduces Golang’s viper package with Go code examples.

Looking to learn Go or Golang in an online course environment? We have a list of the Best Online Courses to Learn Go and Golang to help you get started.

What is the viper Library in Go and Golang?

As mentioned, viper is a package that provides a complete configuration solution in a Go project. Managing and maintaining configuration for a big and complicated application – such as building a server application or any other application which depends a lot on user manipulation of configurations – is not an easy task. Moreover, modern applications are built to deploy in different types of environments, such as in Docker, cloud infrastructures, and so forth. As a result, in order to maintain consistency across deployment, applications should be built to be open from little to high configurability. An external support that helps in this respect is not only a respite, but also very much welcome for the developers involved in building such a solution.

The viper library, in this respect, can entirely replace the flag package, which provides provisions for developing UNIX systems, such as command line utilities. According to the viper documentation, viper, apart from being a complete configuration solution for Go applications, also supports 12-Factor apps. 12-Factor app is a methodology for building software-as-a-service (SAAS) applications. Introduced by Heroku, this technique leverages portability, declarative formats, and automation that makes applications more resilient to the adaptive needs of the changing environment of software deployment.

Read: How to Use the flag Package in Go

What Does the viper Library Support in Go?

According to the viper documentation, it supports the following in Go applications:

  • Reading JSON, TOML, YAML, HCL, envfile and Java properties config files. Most configuration information of an application is written in this format. Viper supports most of them.
  • Setting up default configurations
  • Reading environment variables
  • Reading remote configuration systems
  • Reading from command line flags
  • Reading from buffer
  • Setting explicit values

How to Install viper in Go

The steps to install viper are similar to installing any other package in Go. Once a Go application project has been set up properly with the required module file using the go mod init command, a go.mod file will be created. This file maintains the list of packages used in the current project. Just type: go get github.com/spf13/viper to install the viper package. Observe that a new list of packages related to the viper package will be added in the go.mod file.

Go viper Code Example

Suppose we want to get the values of the common Operating System environment variable called PATH. Developers may do so using the following Go code example:

package main

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

func main() {
viper.BindEnv("PATH")
val := viper.Get("PATH")
fmt.Println("PATH:", val)
}

Note that, in the function main(), we used viper.BindEnv to bind a viper key to the environment variable called PATH. It is case sensitive, meaning, as the key is provided, it will use the environment key that matches the key in uppercase if given in uppercase. Since, BindEnv can take more than one argument, each will represent environment variable names that bind to this key and will be taken in the specified order.

The viper.Get function is used to retrieve any value given the key to use. Here, we use it to retrieve the value in the Operating System’s PATH environment variable. Observe in the following Golang code example that we can not only retrieve values from the environment variable, but also set them as required:

viper.BindEnv("GOMAXPROCS")
eval := viper.Get("GOMAXPROCS")
fmt.Println("GOMAXPROCS:", eval) 

viper.Set("GOMAXPROCS", 20)
eval = viper.Get("GOMAXPROCS")
fmt.Println("GOMAXPROCS:", eval)

We can also set new environment variables through Go code, subject to the Operating System’s permission, of course:

viper.BindEnv("MYVARIABLE")
cval := viper.Get("MYVARIABLE")
if cval == nil {
	fmt.Println("MYVARIABLE could not be defined.")
}

Note that the flag package does not offer such flexibility, but the os package in the standard library offers some. However, the viper package makes it much easier to use.

Read: The Best Tools for Remote Developers

How to Read JSON Configuration Files in Go with viper

Sometimes, configuration files are written in a separate configuration file in one of the many different available formats, such as JSON. The viper package is fully equipped to read and extract information stored there. Here is some quick example code of how to read a JSON configuration file in Go.

Let the JSON config file: testJSONConfig.json be as follows:

{
"init-param": {
"installAt": "Philadelphia, PA",
"adminEmail": "[email protected]",
"staticPath": "/content/static"
},
"taglib": {
"taglib-uri":"xyz.tld",
"taglib-loc":"/WEB-INF/tlds/xyz.tld"
}
}

The Go code snippet to read the JSON file is as follows:

viper.SetConfigType("json")
viper.SetConfigFile("./testJSONConfig.json")
fmt.Printf("Using config: %s\n", viper.ConfigFileUsed())
viper.ReadInConfig()

if viper.IsSet("init-param.installAt") {
fmt.Println("init-param.installAt:", viper.Get("init-param.installAt"))
} else {
fmt.Println(" init-param.installAt not set.")
}
if viper.IsSet("init-param.staticPath") {
fmt.Println("init-param.staticPath:", viper.Get("init-param.staticPath"))
} else {
fmt.Println(" init-param.staticPath is not set.")
}

Working with other popular file formats, such as YAML, TOML, HCL, and so on, using viper is more or less similar.

Unmarshalling Through viper in Go

Interestingly, viper also provides the feature of unmarshalling of values from configuration files to Go types such as struct, map, and so on. Here is a quick example of how to unmarshal with viper in Go:

type configType struct {
InstallAt string
Version string
StaticPath string
}

var config configType

err := viper.Unmarshal(&config)
if err != nil {
fmt.Println("Unmarshalling failed!")
}

Note that the marshalling features are typically provided by the package of the file format we want to marshall. For example, if we want to marshall a Go type into a YAML file, then the YAML Go package will provide the marshalling feature.

Final Thoughts on the Go Library viper

This has been a quick overview of the viper package, with a glimpse of its use in Go. More detailed information can be obtained from the viper documentation itself. Understand that viper, after all, is a tool to be used according to the requirement of the software being developed. It supports many excellent features related to storing and retrieving configuration information sought by programmers in modern application development.

Every capability of viper may not be required at the moment, but that should not stop one from using some of its features. Using judiciously is the key. For example, it is better to use configuration files instead of using command line utilities to supply too many configuration parameters and flags. In this situation, the features provided by the viper package can be quite helpful.

Read more Go programming tutorials and Golang development tips.

Source: www.developer.com