Go (Golang) Application Configuration: Libraries and Tools

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Go (Golang) Application Configuration: Libraries and Tools

Configuration is one of the key aspects of developing modern applications in Go. Flexibility, security, and ease of settings management directly impact the stability and scalability of a service. The Golang ecosystem has several mature libraries that handle loading configurations from files (JSON, YAML, TOML), environment variables, command-line flags, and remote sources. In this article, we will look at four of the most popular tools: viper, envconfig, koanf, and cleanenv, as well as basic approaches to managing settings.



Why do you need a separate library for configuration?

The Go standard library provides the flag package for parsing command-line arguments and os.Getenv for reading environment variables. However, real-world projects require:

  • Support for multiple file formats (JSON, YAML, TOML, HCL).
  • Reading from multiple sources with priorities (file → environment variables → flags).
  • Automatic mapping of struct fields to configuration keys.
  • Validation of required fields and types.
  • Hot-reload (reloading configuration without restarting the application).

The libraries described below solve all these tasks.



1. Viper — The Universal King of Configuration

Viper is the most popular configuration library in Go (over 25k stars on GitHub). It supports all major formats, environment variables, remote systems (etcd, Consul), and command-line flags.

Installation

go get github.com/spf13/viper

Usage Example (YAML + environment variables)

package main

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

type Config struct { Port int `mapstructure:"port"` DBHost string `mapstructure:"db_host"` Debug bool `mapstructure:"debug"`}

func main() { viper.SetConfigName("config") // file name without extension viper.SetConfigType("yaml") // format viper.AddConfigPath(".") // search path viper.AutomaticEnv() // automatically read environment variables

if err := viper.ReadInConfig(); err != nil { log.Fatalf("Error reading config: %v", err) }

var cfg Config if err := viper.Unmarshal(&cfg); err != nil { log.Fatalf("Error unmarshaling: %v", err) }

fmt.Printf("Port: %d, DB Host: %s, Debug: %t", cfg.Port, cfg.DBHost, cfg.Debug)}

Features:

  • Support for nested keys via viper.GetString("app.database.host").
  • Priority: explicit call to Set → flag → env → config file → default.
  • Live reload capability via viper.WatchConfig().


2. envconfig — Minimalism for 12-Factor Apps

If your application follows the 12-factor app methodology and uses only environment variables, envconfig is the ideal choice. It automatically populates a struct based on envconfig tags.

Installation

go get github.com/kelseyhightower/envconfig

Example

package main

import ( "fmt" "github.com/kelseyhightower/envconfig")

type Config struct { Port int `envconfig:"PORT" default:"8080"` DBHost string `envconfig:"DB_HOST" required:"true"` Debug bool `envconfig:"DEBUG"`}

func main() { var cfg Config if err := envconfig.Process("myapp", &cfg); err != nil { panic(err) } fmt.Printf("Config: %+v", cfg)}

Advantages:

  • Minimal code — just declare a struct

Recommendations