| name | Viper Configuration |
| description | This skill should be used when the user asks to "setup Viper", "configuration management", "load config files", "environment variables", "Viper with Cobra", or works with application configuration in Go. |
| version | 0.1.0 |
Viper Configuration
Viper is a complete configuration solution for Go applications supporting multiple formats and sources.
Core Concepts
Configuration Sources (Priority Order)
- Explicit
Set() calls
- Command-line flags
- Environment variables
- Configuration files
- Key/value store (etcd/Consul)
- Defaults
Basic Setup
package config
import (
"fmt"
"github.com/spf13/viper"
"strings"
)
var Config *viper.Viper
func Init() error {
Config = viper.New()
Config.SetConfigName("config")
Config.SetConfigType("yaml")
Config.AddConfigPath(".")
Config.AddConfigPath("./config")
Config.AddConfigPath("/etc/myapp/")
Config.AddConfigPath("$HOME/.myapp")
setDefaults()
if err := Config.ReadInConfig(); err != nil {
if _, ok := err.(viper.ConfigFileNotFoundError); !ok {
return fmt.Errorf("error reading config file: %w", err)
}
}
setupEnvironment()
return nil
}
func setDefaults() {
Config.SetDefault("server.port", "8080")
Config.SetDefault("server.host", "0.0.0.0")
Config.SetDefault("server.readTimeout", 30)
Config.SetDefault("server.writeTimeout", 30)
Config.SetDefault("database.host", "localhost")
Config.SetDefault("database.port", 3306)
Config.SetDefault("database.name", "myapp")
Config.SetDefault("database.maxOpenConns", 25)
Config.SetDefault("database.maxIdleConns", 5)
Config.SetDefault("log.level", "info")
Config.SetDefault("log.format", "json")
}
func setupEnvironment() {
Config.SetEnvPrefix("MYAPP")
Config.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
Config.AutomaticEnv()
}
Configuration File Formats
YAML (config.yaml):
server:
port: "8080"
host: "0.0.0.0"
readTimeout: 30
writeTimeout: 30
database:
host: "localhost"
port: 3306
user: "root"
password: "secret"
name: "myapp"
sslMode: "disable"
maxOpenConns: 25
maxIdleConns: 5
redis:
host: "localhost"
port: 6379
password: ""
db: 0
features:
enableCache: true
enableMetrics: true
rateLimit:
enabled: true
requestsPerSecond: 100
JSON (config.json):
{
"server": {
"port": "8080",
"host": "0.0.0.0"
},
"database": {
"host": "localhost",
"port": 3306
}
}
Reading Configuration Values
port := Config.GetString("server.port")
host := Config.GetString("server.host")
dbPort := Config.GetInt("database.port")
timeout := Config.GetInt("server.readTimeout")
cacheEnabled := Config.GetBool("features.enableCache")
rateLimit := Config.GetFloat64("features.rateLimit.requestsPerSecond")
timeout := Config.GetDuration("server.timeout")
allowedHosts := Config.GetStringSlice("server.allowedHosts")
featureFlags := Config.GetStringMap("features")
rateLimitConfig := Config.GetStringMapString("features.rateLimit")
if Config.IsSet("database.password") {
}
allSettings := Config.AllSettings()
Environment Variables
export MYAPP_SERVER_PORT=9090
export MYAPP_DATABASE_HOST=db.example.com
export MYAPP_DATABASE_PORT=5432
port := Config.GetString("server.port")
host := Config.GetString("database.host")
Bind to Struct
type ServerConfig struct {
Port string `mapstructure:"port"`
Host string `mapstructure:"host"`
ReadTimeout int `mapstructure:"readTimeout"`
WriteTimeout int `mapstructure:"writeTimeout"`
}
type DatabaseConfig struct {
Host string `mapstructure:"host"`
Port int `mapstructure:"port"`
User string `mapstructure:"user"`
Password string `mapstructure:"password"`
Name string `mapstructure:"name"`
SSLMode string `mapstructure:"sslMode"`
MaxOpenConns int `mapstructure:"maxOpenConns"`
MaxIdleConns int `mapstructure:"maxIdleConns"`
}
type Config struct {
Server ServerConfig `mapstructure:"server"`
Database DatabaseConfig `mapstructure:"database"`
}
var cfg Config
if err := Config.Unmarshal(&cfg); err != nil {
return fmt.Errorf("unable to decode config: %w", err)
}
Cobra Integration
package cmd
import (
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
var (
cfgFile string
rootCmd = &cobra.Command{
Use: "myapp",
Short: "My application",
Long: `A longer description of my application`,
}
)
func Execute() error {
return rootCmd.Execute()
}
func init() {
cobra.OnInitialize(initConfig)
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.myapp.yaml)")
rootCmd.PersistentFlags().StringP("server.port", "p", "8080", "Server port")
rootCmd.PersistentFlags().String("server.host", "0.0.0.0", "Server host")
rootCmd.PersistentFlags().String("log.level", "info", "Log level")
viper.BindPFlag("server.port", rootCmd.PersistentFlags().Lookup("server.port"))
viper.BindPFlag("server.host", rootCmd.PersistentFlags().Lookup("server.host"))
viper.BindPFlag("log.level", rootCmd.PersistentFlags().Lookup("log.level"))
viper.SetDefault("server.port", "8080")
}
func initConfig() {
if cfgFile != "" {
viper.SetConfigFile(cfgFile)
} else {
home, _ := os.UserHomeDir()
viper.AddConfigPath(home)
viper.SetConfigName(".myapp")
}
viper.AutomaticEnv()
viper.SetEnvPrefix("MYAPP")
if err := viper.ReadInConfig(); err == nil {
fmt.Println("Using config file:", viper.ConfigFileUsed())
}
}
Multiple Config Files
viper.SetConfigName("config")
viper.AddConfigPath(".")
viper.ReadInConfig()
env := viper.GetString("environment")
viper.SetConfigName("config." + env)
viper.MergeInConfig()
Configuration Validation
func ValidateConfig() error {
required := []string{
"database.host",
"database.name",
"server.port",
}
for _, key := range required {
if !Config.IsSet(key) {
return fmt.Errorf("required configuration missing: %s", key)
}
}
port := Config.GetInt("server.port")
if port < 1 || port > 65535 {
return fmt.Errorf("invalid server port: %d", port)
}
return nil
}
Watching Configuration Changes
func WatchConfig() {
Config.WatchConfig()
Config.OnConfigChange(func(e fsnotify.Event) {
fmt.Println("Config file changed:", e.Name)
})
}
Best Practices
- Use struct tags for clean mapping
- Set sensible defaults for all configuration
- Use environment prefix to avoid conflicts
- Validate configuration at startup
- Use nested keys for organization
- Document configuration options
Additional Resources
references/config-patterns.md - Advanced configuration patterns
examples/viper-cobra/ - Complete integration example