BudiBadu Logo

Samplebadu

Code with Example
BudiBadu Logo
Samplebadu

Go by Example: Configuration with Viper

Go 1.23

Manage application configuration effectively with Viper. This example demonstrates how to read configuration from files (JSON, YAML, etc.), set defaults, and access values, providing a robust solution for 12-factor apps.

Code

package main

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

func main() {
    viper.SetConfigFile("config.yaml")
    viper.SetConfigType("yaml")
    viper.AddConfigPath(".")

    // Set defaults
    viper.SetDefault("port", 8080)
    viper.SetDefault("env", "dev")

    if err := viper.ReadInConfig(); err != nil {
        if _, ok := err.(viper.ConfigFileNotFoundError); ok {
            fmt.Println("Config file not found, using defaults")
        } else {
            panic(fmt.Errorf("fatal error config file: %w", err))
        }
    }

    fmt.Println("Port:", viper.GetInt("port"))
    fmt.Println("Env:", viper.GetString("env"))
    
    // Nested configuration
    fmt.Println("Database Host:", viper.GetString("database.host"))
}

Explanation

Viper is the comprehensive configuration solution for Go, designed to handle the complexity of modern "12-Factor" applications. It unifies configuration from multiple sources, allowing your app to run seamlessly in local, development, and production environments.

Viper resolves configuration keys based on a strict precedence order (highest to lowest):

  1. Explicit calls: viper.Set()
  2. Flags: Command-line flags (when bound to Viper)
  3. Environment: Environment variables (e.g., APP_PORT=9090)
  4. Config File: Values from JSON, YAML, TOML, etc.
  5. Defaults: viper.SetDefault()

This layering allows you to define sensible defaults, override them with a config file for general settings, and use environment variables or flags for specific deployment overrides.

Code Breakdown

9
SetConfigFile specifies the exact config file to use. Alternatively, you can use SetConfigName (without extension) and AddConfigPath to search multiple directories.
10
SetConfigType tells Viper the format of the config file. This is required when using SetConfigFile or when the file doesn't have an extension.
11
AddConfigPath adds a directory to search for config files. You can call this multiple times to search in multiple locations (e.g., /etc/app/, $HOME/.app/, ./).
14-15
SetDefault sets default values for configuration keys. These are used when the key isn't found in any other source. This ensures your app has sensible defaults even without a config file.
17-21
ReadInConfig attempts to find and read the configuration file. We handle two cases: file not found (use defaults) and other errors (fatal). This graceful degradation is a best practice.
25-26
Accessing configuration values using type-safe getters (GetInt, GetString, GetBool, etc.). Viper handles type conversion automatically.
29
Accessing nested configuration using dot notation. "database.host" accesses the 'host' key inside the 'database' section of your config file.