This document covers binding environment variables and command-line flags to configuration keys.
func AutomaticEnv()
func (*Viper) AutomaticEnv()Makes Viper check if environment variables match any of the existing keys (config, default or flags). If matching env vars are found, they are loaded into Viper.
When enabled, Viper will check for an environment variable any time a Get request is made. The env variable name will be the key uppercased and prefixed with the EnvPrefix if set.
Important: Environment variables are case sensitive.
Example:
viper.SetDefault("port", 8080)
viper.AutomaticEnv()
os.Setenv("PORT", "9090")
port := viper.GetInt("port") // Returns 9090func BindEnv(input ...string) error
func (*Viper) BindEnv(input ...string) errorBinds a Viper key to an ENV variable. ENV variables are case sensitive.
Example:
// Bind key to env var with same name (uppercased)
viper.BindEnv("port") // Looks for PORT env var
os.Setenv("PORT", "8080")
port := viper.GetInt("port") // Returns 8080
// Bind key to explicitly named env var
viper.BindEnv("database_url", "DB_CONNECTION_STRING")
os.Setenv("DB_CONNECTION_STRING", "postgres://...")
url := viper.GetString("database_url")
// Bind with multiple env var names (first one wins)
viper.BindEnv("host", "SERVER_HOST", "HOST")func MustBindEnv(input ...string)
func (*Viper) MustBindEnv(input ...string)Wraps BindEnv in a panic. If there is an error binding an environment variable, MustBindEnv will panic.
func SetEnvPrefix(in string)
func (*Viper) SetEnvPrefix(in string)Defines a prefix that ENVIRONMENT variables will use. For example, if your prefix is "spf", the env registry will look for env variables that start with "SPF_".
func GetEnvPrefix() string
func (*Viper) GetEnvPrefix() stringReturns the environment variable prefix.
Example:
viper.SetEnvPrefix("myapp")
viper.AutomaticEnv()
os.Setenv("MYAPP_PORT", "8080")
os.Setenv("MYAPP_HOST", "localhost")
port := viper.GetInt("port") // Looks for MYAPP_PORT
host := viper.GetString("host") // Looks for MYAPP_HOSTfunc SetEnvKeyReplacer(r *strings.Replacer)
func (*Viper) SetEnvKeyReplacer(r *strings.Replacer)Sets the strings.Replacer on the viper object. Useful for mapping an environmental variable to a key that does not match it.
Example:
// Replace dashes with underscores in env var names
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_", "-", "_"))
viper.AutomaticEnv()
os.Setenv("LOG_LEVEL", "debug")
level := viper.GetString("log.level") // Reads from LOG_LEVELfunc AllowEmptyEnv(allowEmptyEnv bool)
func (*Viper) AllowEmptyEnv(allowEmptyEnv bool)Tells Viper to consider set, but empty environment variables as valid values instead of falling back to the next configuration source.
By default, empty environment variables are considered unset and will fall back. Setting this to true treats empty values as set.
Example:
viper.SetDefault("api_key", "default_key")
viper.AllowEmptyEnv(true)
viper.AutomaticEnv()
os.Setenv("API_KEY", "")
// With AllowEmptyEnv(true): returns ""
// With AllowEmptyEnv(false): returns "default_key"
key := viper.GetString("api_key")Viper provides integration with the pflag library (used by Cobra).
type FlagValue interface {
HasChanged() bool
Name() string
ValueString() string
ValueType() string
}Interface that users can implement to bind different flags to viper.
type FlagValueSet interface {
VisitAll(fn func(FlagValue))
}Interface that users can implement to bind a set of flags to viper.
func BindPFlag(key string, flag *pflag.Flag) error
func (*Viper) BindPFlag(key string, flag *pflag.Flag) errorBinds a specific key to a pflag (as used by cobra).
Example:
import (
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/spf13/viper"
)
var rootCmd = &cobra.Command{
Use: "myapp",
Run: func(cmd *cobra.Command, args []string) {
port := viper.GetInt("port")
fmt.Println("Port:", port)
},
}
func init() {
rootCmd.Flags().Int("port", 8080, "Server port")
viper.BindPFlag("port", rootCmd.Flags().Lookup("port"))
}func BindPFlags(flags *pflag.FlagSet) error
func (*Viper) BindPFlags(flags *pflag.FlagSet) errorBinds a full flag set to the configuration, using each flag's long name as the config key.
Example:
flags := pflag.NewFlagSet("myapp", pflag.ContinueOnError)
flags.Int("port", 8080, "Server port")
flags.String("host", "localhost", "Server host")
flags.Bool("debug", false, "Enable debug mode")
viper.BindPFlags(flags)
flags.Parse(os.Args[1:])func BindFlagValue(key string, flag FlagValue) error
func (*Viper) BindFlagValue(key string, flag FlagValue) errorBinds a specific key to a FlagValue.
func BindFlagValues(flags FlagValueSet) error
func (*Viper) BindFlagValues(flags FlagValueSet) errorBinds a full FlagValue set to the configuration, using each flag's long name as the config key.
When creating a Viper instance with options, you can customize environment variable behavior:
type StringReplacer interface {
Replace(s string) string
}Applies a set of replacements to a string.
func EnvKeyReplacer(r StringReplacer) OptionSets a replacer used for mapping environment variables to internal keys. This is more flexible than SetEnvKeyReplacer as it accepts the StringReplacer interface.
Example:
type customReplacer struct{}
func (c customReplacer) Replace(s string) string {
return strings.ReplaceAll(strings.ToUpper(s), ".", "_")
}
v := viper.NewWithOptions(viper.EnvKeyReplacer(customReplacer{}))package main
import (
"fmt"
"os"
"github.com/spf13/pflag"
"github.com/spf13/viper"
)
func main() {
// 1. Set defaults
viper.SetDefault("port", 8080)
viper.SetDefault("host", "localhost")
viper.SetDefault("debug", false)
// 2. Setup environment variables
viper.SetEnvPrefix("myapp")
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
viper.AutomaticEnv()
// 3. Setup command-line flags
pflag.Int("port", 8080, "Server port")
pflag.String("host", "localhost", "Server host")
pflag.Bool("debug", false, "Enable debug mode")
pflag.Parse()
viper.BindPFlags(pflag.CommandLine)
// 4. Read config file (optional)
viper.SetConfigName("config")
viper.AddConfigPath(".")
viper.ReadInConfig() // Ignore errors
// 5. Get values (priority: flags > env > config > defaults)
port := viper.GetInt("port")
host := viper.GetString("host")
debug := viper.GetBool("debug")
fmt.Printf("Server: %s:%d (debug: %v)\n", host, port, debug)
}// Demonstrate priority order
viper.SetDefault("value", "default")
fmt.Println(viper.GetString("value")) // "default"
// Config file sets it to "from-config"
viper.ReadInConfig()
fmt.Println(viper.GetString("value")) // "from-config"
// Environment variable overrides
os.Setenv("VALUE", "from-env")
viper.AutomaticEnv()
fmt.Println(viper.GetString("value")) // "from-env"
// Flag overrides (if bound)
// Assume flag was set to "from-flag"
fmt.Println(viper.GetString("value")) // "from-flag"
// Explicit Set overrides everything
viper.Set("value", "explicit")
fmt.Println(viper.GetString("value")) // "explicit"// Pattern 1: Automatic binding with prefix
viper.SetEnvPrefix("app")
viper.AutomaticEnv()
os.Setenv("APP_DATABASE_HOST", "db.example.com")
host := viper.GetString("database.host") // "db.example.com"
// Pattern 2: Explicit binding
viper.BindEnv("db_url", "DATABASE_URL")
os.Setenv("DATABASE_URL", "postgres://...")
url := viper.GetString("db_url")
// Pattern 3: Multiple env var names
viper.BindEnv("port", "SERVER_PORT", "PORT", "HTTP_PORT")
// Will use first env var that is set
// Pattern 4: Empty values
viper.AllowEmptyEnv(true)
viper.BindEnv("optional_value")
os.Setenv("OPTIONAL_VALUE", "")
value := viper.GetString("optional_value") // "" (not fallback)