Go configuration with fangs - A complete configuration solution for Go applications
Viper is a complete configuration solution for Go applications including 12-Factor apps. It handles all types of configuration needs and formats, providing a prioritized configuration registry that manages multiple configuration sources.
go get github.com/spf13/vipergithub.com/spf13/viperimport "github.com/spf13/viper"For remote configuration features:
import _ "github.com/spf13/viper/remote"package main
import (
"fmt"
"github.com/spf13/viper"
)
func main() {
// Set defaults
viper.SetDefault("port", 8080)
viper.SetDefault("host", "localhost")
// Read from config file
viper.SetConfigName("config")
viper.SetConfigType("yaml")
viper.AddConfigPath(".")
if err := viper.ReadInConfig(); err != nil {
if _, ok := err.(viper.ConfigFileNotFoundError); !ok {
panic(err)
}
}
// Read from environment
viper.AutomaticEnv()
// Get values
port := viper.GetInt("port")
host := viper.GetString("host")
fmt.Printf("Server: %s:%d\n", host, port)
}Viper uses the following precedence order (highest to lowest priority):
Set()Important: Viper configuration keys are case-insensitive.
type Viper struct {
// Has unexported fields
}The main configuration management type. Maintains a set of configuration sources and provides values according to priority order.
Note: Viper instances are NOT safe for concurrent Get() and Set() operations.
Constructor Functions:
func New() *Viper
func NewWithOptions(opts ...Option) *Viper
func GetViper() *ViperNew() - Creates a new independent Viper instanceNewWithOptions(opts) - Creates a new Viper instance with configuration optionsGetViper() - Returns the global Viper instanceViper provides both package-level functions (operating on a global instance) and methods on *Viper instances. For example:
// Using global instance
viper.Set("key", "value")
value := viper.GetString("key")
// Using custom instance
v := viper.New()
v.Set("key", "value")
value := v.GetString("key")var SupportedExts = []string{
"json", "toml", "yaml", "yml",
"properties", "props", "prop",
"hcl", "tfvars", "dotenv", "env", "ini"
}Viper supports JSON, TOML, YAML, HCL, INI, dotenv, envfile, and Java properties files.
var SupportedRemoteProviders = []string{
"etcd", "etcd3", "consul", "firestore", "nats"
}Read, write, watch, and merge configuration files in multiple formats.
func AddConfigPath(in string)
func SetConfigFile(in string)
func SetConfigName(in string)
func SetConfigType(in string)
func ReadInConfig() error
func WriteConfig() error
func SafeWriteConfig() errorKey Functions:
AddConfigPath - Adds search paths for config filesSetConfigFile - Sets explicit config file pathSetConfigName - Sets config file name (without extension)SetConfigType - Sets config file type (json, yaml, etc.)ReadInConfig - Discovers and loads config fileWriteConfig - Writes current config to fileSafeWriteConfig - Writes only if file doesn't existSet defaults, override values, and retrieve configuration values with type-safe getters.
func SetDefault(key string, value any)
func Set(key string, value any)
func Get(key string) any
func GetString(key string) string
func GetInt(key string) int
func GetBool(key string) boolKey Functions:
SetDefault - Sets default value for a keySet - Sets override value (highest priority)Get - Retrieves any valueGetString, GetInt, GetBool, etc. - Type-safe gettersAllKeys - Returns all keysAllSettings - Returns all settings as mapBind environment variables and command-line flags to configuration keys.
func AutomaticEnv()
func BindEnv(input ...string) error
func SetEnvPrefix(in string)
func BindPFlag(key string, flag *pflag.Flag) errorKey Functions:
AutomaticEnv - Automatically check env vars for all keysBindEnv - Bind specific env var to keySetEnvPrefix - Set prefix for env var namesBindPFlag - Bind pflag to keyBindPFlags - Bind entire FlagSetEnvironment Variables and Flags
Read configuration from remote key/value stores like etcd, Consul, Firestore, and NATS.
func AddRemoteProvider(provider, endpoint, path string) error
func AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error
func ReadRemoteConfig() error
func WatchRemoteConfig() errorNote: Requires importing the remote package: import _ "github.com/spf13/viper/remote"
Options for customization, codec registration, unmarshaling to structs, and more.
type Option interface {
// Has unexported methods
}
func KeyDelimiter(d string) Option
func WithLogger(l *slog.Logger) Option
func WithFinder(f Finder) Option
func WithEncoderRegistry(r EncoderRegistry) Option
func WithDecoderRegistry(r DecoderRegistry) Option
func Unmarshal(rawVal any, opts ...DecoderConfigOption) error
func UnmarshalKey(key string, rawVal any, opts ...DecoderConfigOption) errorKey Features:
type ConfigFileNotFoundError struct {
// Has unexported fields
}
type ConfigParseError struct {
// Has unexported fields
}
type UnsupportedConfigError string
type RemoteConfigError stringviper.SetConfigName("config")
viper.SetConfigType("yaml")
viper.AddConfigPath("/etc/myapp/")
viper.AddConfigPath("$HOME/.myapp")
viper.AddConfigPath(".")
err := viper.ReadInConfig()
if err != nil {
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
// Config file not found; use defaults
} else {
// Config file found but error occurred
panic(err)
}
}// 1. Set defaults
viper.SetDefault("port", 8080)
viper.SetDefault("log_level", "info")
// 2. Read config file
viper.SetConfigName("config")
viper.AddConfigPath(".")
viper.ReadInConfig()
// 3. Bind environment variables
viper.SetEnvPrefix("MYAPP")
viper.AutomaticEnv()
// 4. Bind flags
viper.BindPFlag("port", cmd.Flags().Lookup("port"))
// Values retrieved with precedence: flags > env > config > defaults
port := viper.GetInt("port")viper.OnConfigChange(func(e fsnotify.Event) {
fmt.Println("Config file changed:", e.Name)
})
viper.WatchConfig()type Config struct {
Port int `mapstructure:"port"`
Host string `mapstructure:"host"`
LogLevel string `mapstructure:"log_level"`
}
var config Config
err := viper.Unmarshal(&config)Viper instances are NOT safe for concurrent Get() and Set() operations. If you need concurrent access, use appropriate synchronization mechanisms or separate Viper instances per goroutine.
Install with Tessl CLI
npx tessl i tessl/go-viper