github.com/fengjian1993/viper@v1.11.0/README.md (about)

     1  > ## Viper v2 feedback
     2  > Viper is heading towards v2 and we would love to hear what _**you**_ would like to see in it. Share your thoughts here: https://forms.gle/R6faU74qPRPAzchZ9
     3  >
     4  > **Thank you!**
     5  
     6  ![Viper](.github/logo.png?raw=true)
     7  
     8  [![Mentioned in Awesome Go](https://awesome.re/mentioned-badge-flat.svg)](https://github.com/avelino/awesome-go#configuration)
     9  [![run on repl.it](https://repl.it/badge/github/sagikazarmark/Viper-example)](https://repl.it/@sagikazarmark/Viper-example#main.go)
    10  
    11  [![GitHub Workflow Status](https://img.shields.io/github/workflow/status/spf13/viper/CI?style=flat-square)](https://github.com/spf13/viper/actions?query=workflow%3ACI)
    12  [![Join the chat at https://gitter.im/spf13/viper](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/spf13/viper?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
    13  [![Go Report Card](https://goreportcard.com/badge/github.com/spf13/viper?style=flat-square)](https://goreportcard.com/report/github.com/spf13/viper)
    14  ![Go Version](https://img.shields.io/badge/go%20version-%3E=1.14-61CFDD.svg?style=flat-square)
    15  [![PkgGoDev](https://pkg.go.dev/badge/mod/github.com/spf13/viper)](https://pkg.go.dev/mod/github.com/spf13/viper)
    16  
    17  **Go configuration with fangs!**
    18  
    19  Many Go projects are built using Viper including:
    20  
    21  * [Hugo](http://gohugo.io)
    22  * [EMC RexRay](http://rexray.readthedocs.org/en/stable/)
    23  * [Imgur’s Incus](https://github.com/Imgur/incus)
    24  * [Nanobox](https://github.com/nanobox-io/nanobox)/[Nanopack](https://github.com/nanopack)
    25  * [Docker Notary](https://github.com/docker/Notary)
    26  * [BloomApi](https://www.bloomapi.com/)
    27  * [doctl](https://github.com/digitalocean/doctl)
    28  * [Clairctl](https://github.com/jgsqware/clairctl)
    29  * [Mercure](https://mercure.rocks)
    30  
    31  
    32  ## Install
    33  
    34  ```shell
    35  go get github.com/spf13/viper
    36  ```
    37  
    38  **Note:** Viper uses [Go Modules](https://github.com/golang/go/wiki/Modules) to manage dependencies.
    39  
    40  
    41  ## What is Viper?
    42  
    43  Viper is a complete configuration solution for Go applications including 12-Factor apps. It is designed
    44  to work within an application, and can handle all types of configuration needs
    45  and formats. It supports:
    46  
    47  * setting defaults
    48  * reading from JSON, TOML, YAML, HCL, envfile and Java properties config files
    49  * live watching and re-reading of config files (optional)
    50  * reading from environment variables
    51  * reading from remote config systems (etcd or Consul), and watching changes
    52  * reading from command line flags
    53  * reading from buffer
    54  * setting explicit values
    55  
    56  Viper can be thought of as a registry for all of your applications configuration needs.
    57  
    58  
    59  ## Why Viper?
    60  
    61  When building a modern application, you don’t want to worry about
    62  configuration file formats; you want to focus on building awesome software.
    63  Viper is here to help with that.
    64  
    65  Viper does the following for you:
    66  
    67  1. Find, load, and unmarshal a configuration file in JSON, TOML, YAML, HCL, INI, envfile or Java properties formats.
    68  2. Provide a mechanism to set default values for your different configuration options.
    69  3. Provide a mechanism to set override values for options specified through command line flags.
    70  4. Provide an alias system to easily rename parameters without breaking existing code.
    71  5. Make it easy to tell the difference between when a user has provided a command line or config file which is the same as the default.
    72  
    73  Viper uses the following precedence order. Each item takes precedence over the item below it:
    74  
    75   * explicit call to `Set`
    76   * flag
    77   * env
    78   * config
    79   * key/value store
    80   * default
    81  
    82  **Important:** Viper configuration keys are case insensitive.
    83  There are ongoing discussions about making that optional.
    84  
    85  
    86  ## Putting Values into Viper
    87  
    88  ### Establishing Defaults
    89  
    90  A good configuration system will support default values. A default value is not
    91  required for a key, but it’s useful in the event that a key hasn't been set via
    92  config file, environment variable, remote configuration or flag.
    93  
    94  Examples:
    95  
    96  ```go
    97  viper.SetDefault("ContentDir", "content")
    98  viper.SetDefault("LayoutDir", "layouts")
    99  viper.SetDefault("Taxonomies", map[string]string{"tag": "tags", "category": "categories"})
   100  ```
   101  
   102  ### Reading Config Files
   103  
   104  Viper requires minimal configuration so it knows where to look for config files.
   105  Viper supports JSON, TOML, YAML, HCL, INI, envfile and Java Properties files. Viper can search multiple paths, but
   106  currently a single Viper instance only supports a single configuration file.
   107  Viper does not default to any configuration search paths leaving defaults decision
   108  to an application.
   109  
   110  Here is an example of how to use Viper to search for and read a configuration file.
   111  None of the specific paths are required, but at least one path should be provided
   112  where a configuration file is expected.
   113  
   114  ```go
   115  viper.SetConfigName("config") // name of config file (without extension)
   116  viper.SetConfigType("yaml") // REQUIRED if the config file does not have the extension in the name
   117  viper.AddConfigPath("/etc/appname/")   // path to look for the config file in
   118  viper.AddConfigPath("$HOME/.appname")  // call multiple times to add many search paths
   119  viper.AddConfigPath(".")               // optionally look for config in the working directory
   120  err := viper.ReadInConfig() // Find and read the config file
   121  if err != nil { // Handle errors reading the config file
   122  	panic(fmt.Errorf("Fatal error config file: %w \n", err))
   123  }
   124  ```
   125  
   126  You can handle the specific case where no config file is found like this:
   127  
   128  ```go
   129  if err := viper.ReadInConfig(); err != nil {
   130  	if _, ok := err.(viper.ConfigFileNotFoundError); ok {
   131  		// Config file not found; ignore error if desired
   132  	} else {
   133  		// Config file was found but another error was produced
   134  	}
   135  }
   136  
   137  // Config file found and successfully parsed
   138  ```
   139  
   140  *NOTE [since 1.6]:* You can also have a file without an extension and specify the format programmaticaly. For those configuration files that lie in the home of the user without any extension like `.bashrc`
   141  
   142  ### Writing Config Files
   143  
   144  Reading from config files is useful, but at times you want to store all modifications made at run time.
   145  For that, a bunch of commands are available, each with its own purpose:
   146  
   147  * WriteConfig - writes the current viper configuration to the predefined path, if exists. Errors if no predefined path. Will overwrite the current config file, if it exists.
   148  * SafeWriteConfig - writes the current viper configuration to the predefined path. Errors if no predefined path. Will not overwrite the current config file, if it exists.
   149  * WriteConfigAs - writes the current viper configuration to the given filepath. Will overwrite the given file, if it exists.
   150  * SafeWriteConfigAs - writes the current viper configuration to the given filepath. Will not overwrite the given file, if it exists.
   151  
   152  As a rule of the thumb, everything marked with safe won't overwrite any file, but just create if not existent, whilst the default behavior is to create or truncate.
   153  
   154  A small examples section:
   155  
   156  ```go
   157  viper.WriteConfig() // writes current config to predefined path set by 'viper.AddConfigPath()' and 'viper.SetConfigName'
   158  viper.SafeWriteConfig()
   159  viper.WriteConfigAs("/path/to/my/.config")
   160  viper.SafeWriteConfigAs("/path/to/my/.config") // will error since it has already been written
   161  viper.SafeWriteConfigAs("/path/to/my/.other_config")
   162  ```
   163  
   164  ### Watching and re-reading config files
   165  
   166  Viper supports the ability to have your application live read a config file while running.
   167  
   168  Gone are the days of needing to restart a server to have a config take effect,
   169  viper powered applications can read an update to a config file while running and
   170  not miss a beat.
   171  
   172  Simply tell the viper instance to watchConfig.
   173  Optionally you can provide a function for Viper to run each time a change occurs.
   174  
   175  **Make sure you add all of the configPaths prior to calling `WatchConfig()`**
   176  
   177  ```go
   178  viper.OnConfigChange(func(e fsnotify.Event) {
   179  	fmt.Println("Config file changed:", e.Name)
   180  })
   181  viper.WatchConfig()
   182  ```
   183  
   184  ### Reading Config from io.Reader
   185  
   186  Viper predefines many configuration sources such as files, environment
   187  variables, flags, and remote K/V store, but you are not bound to them. You can
   188  also implement your own required configuration source and feed it to viper.
   189  
   190  ```go
   191  viper.SetConfigType("yaml") // or viper.SetConfigType("YAML")
   192  
   193  // any approach to require this configuration into your program.
   194  var yamlExample = []byte(`
   195  Hacker: true
   196  name: steve
   197  hobbies:
   198  - skateboarding
   199  - snowboarding
   200  - go
   201  clothing:
   202    jacket: leather
   203    trousers: denim
   204  age: 35
   205  eyes : brown
   206  beard: true
   207  `)
   208  
   209  viper.ReadConfig(bytes.NewBuffer(yamlExample))
   210  
   211  viper.Get("name") // this would be "steve"
   212  ```
   213  
   214  ### Setting Overrides
   215  
   216  These could be from a command line flag, or from your own application logic.
   217  
   218  ```go
   219  viper.Set("Verbose", true)
   220  viper.Set("LogFile", LogFile)
   221  ```
   222  
   223  ### Registering and Using Aliases
   224  
   225  Aliases permit a single value to be referenced by multiple keys
   226  
   227  ```go
   228  viper.RegisterAlias("loud", "Verbose")
   229  
   230  viper.Set("verbose", true) // same result as next line
   231  viper.Set("loud", true)   // same result as prior line
   232  
   233  viper.GetBool("loud") // true
   234  viper.GetBool("verbose") // true
   235  ```
   236  
   237  ### Working with Environment Variables
   238  
   239  Viper has full support for environment variables. This enables 12 factor
   240  applications out of the box. There are five methods that exist to aid working
   241  with ENV:
   242  
   243   * `AutomaticEnv()`
   244   * `BindEnv(string...) : error`
   245   * `SetEnvPrefix(string)`
   246   * `SetEnvKeyReplacer(string...) *strings.Replacer`
   247   * `AllowEmptyEnv(bool)`
   248  
   249  _When working with ENV variables, it’s important to recognize that Viper
   250  treats ENV variables as case sensitive._
   251  
   252  Viper provides a mechanism to try to ensure that ENV variables are unique. By
   253  using `SetEnvPrefix`, you can tell Viper to use a prefix while reading from
   254  the environment variables. Both `BindEnv` and `AutomaticEnv` will use this
   255  prefix.
   256  
   257  `BindEnv` takes one or more parameters. The first parameter is the key name, the
   258  rest are the name of the environment variables to bind to this key. If more than
   259  one are provided, they will take precedence in the specified order. The name of
   260  the environment variable is case sensitive. If the ENV variable name is not provided, then
   261  Viper will automatically assume that the ENV variable matches the following format: prefix + "_" + the key name in ALL CAPS. When you explicitly provide the ENV variable name (the second parameter),
   262  it **does not** automatically add the prefix. For example if the second parameter is "id",
   263  Viper will look for the ENV variable "ID".
   264  
   265  One important thing to recognize when working with ENV variables is that the
   266  value will be read each time it is accessed. Viper does not fix the value when
   267  the `BindEnv` is called.
   268  
   269  `AutomaticEnv` is a powerful helper especially when combined with
   270  `SetEnvPrefix`. When called, Viper will check for an environment variable any
   271  time a `viper.Get` request is made. It will apply the following rules. It will
   272  check for an environment variable with a name matching the key uppercased and
   273  prefixed with the `EnvPrefix` if set.
   274  
   275  `SetEnvKeyReplacer` allows you to use a `strings.Replacer` object to rewrite Env
   276  keys to an extent. This is useful if you want to use `-` or something in your
   277  `Get()` calls, but want your environmental variables to use `_` delimiters. An
   278  example of using it can be found in `viper_test.go`.
   279  
   280  Alternatively, you can use `EnvKeyReplacer` with `NewWithOptions` factory function.
   281  Unlike `SetEnvKeyReplacer`, it accepts a `StringReplacer` interface allowing you to write custom string replacing logic.
   282  
   283  By default empty environment variables are considered unset and will fall back to
   284  the next configuration source. To treat empty environment variables as set, use
   285  the `AllowEmptyEnv` method.
   286  
   287  #### Env example
   288  
   289  ```go
   290  SetEnvPrefix("spf") // will be uppercased automatically
   291  BindEnv("id")
   292  
   293  os.Setenv("SPF_ID", "13") // typically done outside of the app
   294  
   295  id := Get("id") // 13
   296  ```
   297  
   298  ### Working with Flags
   299  
   300  Viper has the ability to bind to flags. Specifically, Viper supports `Pflags`
   301  as used in the [Cobra](https://github.com/spf13/cobra) library.
   302  
   303  Like `BindEnv`, the value is not set when the binding method is called, but when
   304  it is accessed. This means you can bind as early as you want, even in an
   305  `init()` function.
   306  
   307  For individual flags, the `BindPFlag()` method provides this functionality.
   308  
   309  Example:
   310  
   311  ```go
   312  serverCmd.Flags().Int("port", 1138, "Port to run Application server on")
   313  viper.BindPFlag("port", serverCmd.Flags().Lookup("port"))
   314  ```
   315  
   316  You can also bind an existing set of pflags (pflag.FlagSet):
   317  
   318  Example:
   319  
   320  ```go
   321  pflag.Int("flagname", 1234, "help message for flagname")
   322  
   323  pflag.Parse()
   324  viper.BindPFlags(pflag.CommandLine)
   325  
   326  i := viper.GetInt("flagname") // retrieve values from viper instead of pflag
   327  ```
   328  
   329  The use of [pflag](https://github.com/spf13/pflag/) in Viper does not preclude
   330  the use of other packages that use the [flag](https://golang.org/pkg/flag/)
   331  package from the standard library. The pflag package can handle the flags
   332  defined for the flag package by importing these flags. This is accomplished
   333  by a calling a convenience function provided by the pflag package called
   334  AddGoFlagSet().
   335  
   336  Example:
   337  
   338  ```go
   339  package main
   340  
   341  import (
   342  	"flag"
   343  	"github.com/spf13/pflag"
   344  )
   345  
   346  func main() {
   347  
   348  	// using standard library "flag" package
   349  	flag.Int("flagname", 1234, "help message for flagname")
   350  
   351  	pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
   352  	pflag.Parse()
   353  	viper.BindPFlags(pflag.CommandLine)
   354  
   355  	i := viper.GetInt("flagname") // retrieve value from viper
   356  
   357  	// ...
   358  }
   359  ```
   360  
   361  #### Flag interfaces
   362  
   363  Viper provides two Go interfaces to bind other flag systems if you don’t use `Pflags`.
   364  
   365  `FlagValue` represents a single flag. This is a very simple example on how to implement this interface:
   366  
   367  ```go
   368  type myFlag struct {}
   369  func (f myFlag) HasChanged() bool { return false }
   370  func (f myFlag) Name() string { return "my-flag-name" }
   371  func (f myFlag) ValueString() string { return "my-flag-value" }
   372  func (f myFlag) ValueType() string { return "string" }
   373  ```
   374  
   375  Once your flag implements this interface, you can simply tell Viper to bind it:
   376  
   377  ```go
   378  viper.BindFlagValue("my-flag-name", myFlag{})
   379  ```
   380  
   381  `FlagValueSet` represents a group of flags. This is a very simple example on how to implement this interface:
   382  
   383  ```go
   384  type myFlagSet struct {
   385  	flags []myFlag
   386  }
   387  
   388  func (f myFlagSet) VisitAll(fn func(FlagValue)) {
   389  	for _, flag := range flags {
   390  		fn(flag)
   391  	}
   392  }
   393  ```
   394  
   395  Once your flag set implements this interface, you can simply tell Viper to bind it:
   396  
   397  ```go
   398  fSet := myFlagSet{
   399  	flags: []myFlag{myFlag{}, myFlag{}},
   400  }
   401  viper.BindFlagValues("my-flags", fSet)
   402  ```
   403  
   404  ### Remote Key/Value Store Support
   405  
   406  To enable remote support in Viper, do a blank import of the `viper/remote`
   407  package:
   408  
   409  `import _ "github.com/spf13/viper/remote"`
   410  
   411  Viper will read a config string (as JSON, TOML, YAML, HCL or envfile) retrieved from a path
   412  in a Key/Value store such as etcd or Consul.  These values take precedence over
   413  default values, but are overridden by configuration values retrieved from disk,
   414  flags, or environment variables.
   415  
   416  Viper uses [crypt](https://github.com/bketelsen/crypt) to retrieve
   417  configuration from the K/V store, which means that you can store your
   418  configuration values encrypted and have them automatically decrypted if you have
   419  the correct gpg keyring.  Encryption is optional.
   420  
   421  You can use remote configuration in conjunction with local configuration, or
   422  independently of it.
   423  
   424  `crypt` has a command-line helper that you can use to put configurations in your
   425  K/V store. `crypt` defaults to etcd on http://127.0.0.1:4001.
   426  
   427  ```bash
   428  $ go get github.com/bketelsen/crypt/bin/crypt
   429  $ crypt set -plaintext /config/hugo.json /Users/hugo/settings/config.json
   430  ```
   431  
   432  Confirm that your value was set:
   433  
   434  ```bash
   435  $ crypt get -plaintext /config/hugo.json
   436  ```
   437  
   438  See the `crypt` documentation for examples of how to set encrypted values, or
   439  how to use Consul.
   440  
   441  ### Remote Key/Value Store Example - Unencrypted
   442  
   443  #### etcd
   444  ```go
   445  viper.AddRemoteProvider("etcd", "http://127.0.0.1:4001","/config/hugo.json")
   446  viper.SetConfigType("json") // because there is no file extension in a stream of bytes, supported extensions are "json", "toml", "yaml", "yml", "properties", "props", "prop", "env", "dotenv"
   447  err := viper.ReadRemoteConfig()
   448  ```
   449  
   450  #### Consul
   451  You need to set a key to Consul key/value storage with JSON value containing your desired config.
   452  For example, create a Consul key/value store key `MY_CONSUL_KEY` with value:
   453  
   454  ```json
   455  {
   456      "port": 8080,
   457      "hostname": "myhostname.com"
   458  }
   459  ```
   460  
   461  ```go
   462  viper.AddRemoteProvider("consul", "localhost:8500", "MY_CONSUL_KEY")
   463  viper.SetConfigType("json") // Need to explicitly set this to json
   464  err := viper.ReadRemoteConfig()
   465  
   466  fmt.Println(viper.Get("port")) // 8080
   467  fmt.Println(viper.Get("hostname")) // myhostname.com
   468  ```
   469  
   470  #### Firestore
   471  
   472  ```go
   473  viper.AddRemoteProvider("firestore", "google-cloud-project-id", "collection/document")
   474  viper.SetConfigType("json") // Config's format: "json", "toml", "yaml", "yml"
   475  err := viper.ReadRemoteConfig()
   476  ```
   477  
   478  Of course, you're allowed to use `SecureRemoteProvider` also
   479  
   480  ### Remote Key/Value Store Example - Encrypted
   481  
   482  ```go
   483  viper.AddSecureRemoteProvider("etcd","http://127.0.0.1:4001","/config/hugo.json","/etc/secrets/mykeyring.gpg")
   484  viper.SetConfigType("json") // because there is no file extension in a stream of bytes,  supported extensions are "json", "toml", "yaml", "yml", "properties", "props", "prop", "env", "dotenv"
   485  err := viper.ReadRemoteConfig()
   486  ```
   487  
   488  ### Watching Changes in etcd - Unencrypted
   489  
   490  ```go
   491  // alternatively, you can create a new viper instance.
   492  var runtime_viper = viper.New()
   493  
   494  runtime_viper.AddRemoteProvider("etcd", "http://127.0.0.1:4001", "/config/hugo.yml")
   495  runtime_viper.SetConfigType("yaml") // because there is no file extension in a stream of bytes, supported extensions are "json", "toml", "yaml", "yml", "properties", "props", "prop", "env", "dotenv"
   496  
   497  // read from remote config the first time.
   498  err := runtime_viper.ReadRemoteConfig()
   499  
   500  // unmarshal config
   501  runtime_viper.Unmarshal(&runtime_conf)
   502  
   503  // open a goroutine to watch remote changes forever
   504  go func(){
   505  	for {
   506  		time.Sleep(time.Second * 5) // delay after each request
   507  
   508  		// currently, only tested with etcd support
   509  		err := runtime_viper.WatchRemoteConfig()
   510  		if err != nil {
   511  			log.Errorf("unable to read remote config: %v", err)
   512  			continue
   513  		}
   514  
   515  		// unmarshal new config into our runtime config struct. you can also use channel
   516  		// to implement a signal to notify the system of the changes
   517  		runtime_viper.Unmarshal(&runtime_conf)
   518  	}
   519  }()
   520  ```
   521  
   522  ## Getting Values From Viper
   523  
   524  In Viper, there are a few ways to get a value depending on the value’s type.
   525  The following functions and methods exist:
   526  
   527   * `Get(key string) : interface{}`
   528   * `GetBool(key string) : bool`
   529   * `GetFloat64(key string) : float64`
   530   * `GetInt(key string) : int`
   531   * `GetIntSlice(key string) : []int`
   532   * `GetString(key string) : string`
   533   * `GetStringMap(key string) : map[string]interface{}`
   534   * `GetStringMapString(key string) : map[string]string`
   535   * `GetStringSlice(key string) : []string`
   536   * `GetTime(key string) : time.Time`
   537   * `GetDuration(key string) : time.Duration`
   538   * `IsSet(key string) : bool`
   539   * `AllSettings() : map[string]interface{}`
   540  
   541  One important thing to recognize is that each Get function will return a zero
   542  value if it’s not found. To check if a given key exists, the `IsSet()` method
   543  has been provided.
   544  
   545  Example:
   546  ```go
   547  viper.GetString("logfile") // case-insensitive Setting & Getting
   548  if viper.GetBool("verbose") {
   549  	fmt.Println("verbose enabled")
   550  }
   551  ```
   552  ### Accessing nested keys
   553  
   554  The accessor methods also accept formatted paths to deeply nested keys. For
   555  example, if the following JSON file is loaded:
   556  
   557  ```json
   558  {
   559      "host": {
   560          "address": "localhost",
   561          "port": 5799
   562      },
   563      "datastore": {
   564          "metric": {
   565              "host": "127.0.0.1",
   566              "port": 3099
   567          },
   568          "warehouse": {
   569              "host": "198.0.0.1",
   570              "port": 2112
   571          }
   572      }
   573  }
   574  
   575  ```
   576  
   577  Viper can access a nested field by passing a `.` delimited path of keys:
   578  
   579  ```go
   580  GetString("datastore.metric.host") // (returns "127.0.0.1")
   581  ```
   582  
   583  This obeys the precedence rules established above; the search for the path
   584  will cascade through the remaining configuration registries until found.
   585  
   586  For example, given this configuration file, both `datastore.metric.host` and
   587  `datastore.metric.port` are already defined (and may be overridden). If in addition
   588  `datastore.metric.protocol` was defined in the defaults, Viper would also find it.
   589  
   590  However, if `datastore.metric` was overridden (by a flag, an environment variable,
   591  the `Set()` method, …) with an immediate value, then all sub-keys of
   592  `datastore.metric` become undefined, they are “shadowed” by the higher-priority
   593  configuration level.
   594  
   595  Viper can access array indices by using numbers in the path. For example:
   596  
   597  ```json
   598  {
   599      "host": {
   600          "address": "localhost",
   601          "ports": [
   602              5799,
   603              6029
   604          ]
   605      },
   606      "datastore": {
   607          "metric": {
   608              "host": "127.0.0.1",
   609              "port": 3099
   610          },
   611          "warehouse": {
   612              "host": "198.0.0.1",
   613              "port": 2112
   614          }
   615      }
   616  }
   617  
   618  GetInt("host.ports.1") // returns 6029
   619  
   620  ```
   621  
   622  Lastly, if there exists a key that matches the delimited key path, its value
   623  will be returned instead. E.g.
   624  
   625  ```json
   626  {
   627      "datastore.metric.host": "0.0.0.0",
   628      "host": {
   629          "address": "localhost",
   630          "port": 5799
   631      },
   632      "datastore": {
   633          "metric": {
   634              "host": "127.0.0.1",
   635              "port": 3099
   636          },
   637          "warehouse": {
   638              "host": "198.0.0.1",
   639              "port": 2112
   640          }
   641      }
   642  }
   643  
   644  GetString("datastore.metric.host") // returns "0.0.0.0"
   645  ```
   646  
   647  ### Extracting a sub-tree
   648  
   649  When developing reusable modules, it's often useful to extract a subset of the configuration
   650  and pass it to a module. This way the module can be instantiated more than once, with different configurations.
   651  
   652  For example, an application might use multiple different cache stores for different purposes:
   653  
   654  ```yaml
   655  cache:
   656    cache1:
   657      max-items: 100
   658      item-size: 64
   659    cache2:
   660      max-items: 200
   661      item-size: 80
   662  ```
   663  
   664  We could pass the cache name to a module (eg. `NewCache("cache1")`),
   665  but it would require weird concatenation for accessing config keys and would be less separated from the global config.
   666  
   667  So instead of doing that let's pass a Viper instance to the constructor that represents a subset of the configuration:
   668  
   669  ```go
   670  cache1Config := viper.Sub("cache.cache1")
   671  if cache1Config == nil { // Sub returns nil if the key cannot be found
   672  	panic("cache configuration not found")
   673  }
   674  
   675  cache1 := NewCache(cache1Config)
   676  ```
   677  
   678  **Note:** Always check the return value of `Sub`. It returns `nil` if a key cannot be found.
   679  
   680  Internally, the `NewCache` function can address `max-items` and `item-size` keys directly:
   681  
   682  ```go
   683  func NewCache(v *Viper) *Cache {
   684  	return &Cache{
   685  		MaxItems: v.GetInt("max-items"),
   686  		ItemSize: v.GetInt("item-size"),
   687  	}
   688  }
   689  ```
   690  
   691  The resulting code is easy to test, since it's decoupled from the main config structure,
   692  and easier to reuse (for the same reason).
   693  
   694  
   695  ### Unmarshaling
   696  
   697  You also have the option of Unmarshaling all or a specific value to a struct, map,
   698  etc.
   699  
   700  There are two methods to do this:
   701  
   702   * `Unmarshal(rawVal interface{}) : error`
   703   * `UnmarshalKey(key string, rawVal interface{}) : error`
   704  
   705  Example:
   706  
   707  ```go
   708  type config struct {
   709  	Port int
   710  	Name string
   711  	PathMap string `mapstructure:"path_map"`
   712  }
   713  
   714  var C config
   715  
   716  err := viper.Unmarshal(&C)
   717  if err != nil {
   718  	t.Fatalf("unable to decode into struct, %v", err)
   719  }
   720  ```
   721  
   722  If you want to unmarshal configuration where the keys themselves contain dot (the default key delimiter),
   723  you have to change the delimiter:
   724  
   725  ```go
   726  v := viper.NewWithOptions(viper.KeyDelimiter("::"))
   727  
   728  v.SetDefault("chart::values", map[string]interface{}{
   729  	"ingress": map[string]interface{}{
   730  		"annotations": map[string]interface{}{
   731  			"traefik.frontend.rule.type":                 "PathPrefix",
   732  			"traefik.ingress.kubernetes.io/ssl-redirect": "true",
   733  		},
   734  	},
   735  })
   736  
   737  type config struct {
   738  	Chart struct{
   739  		Values map[string]interface{}
   740  	}
   741  }
   742  
   743  var C config
   744  
   745  v.Unmarshal(&C)
   746  ```
   747  
   748  Viper also supports unmarshaling into embedded structs:
   749  
   750  ```go
   751  /*
   752  Example config:
   753  
   754  module:
   755      enabled: true
   756      token: 89h3f98hbwf987h3f98wenf89ehf
   757  */
   758  type config struct {
   759  	Module struct {
   760  		Enabled bool
   761  
   762  		moduleConfig `mapstructure:",squash"`
   763  	}
   764  }
   765  
   766  // moduleConfig could be in a module specific package
   767  type moduleConfig struct {
   768  	Token string
   769  }
   770  
   771  var C config
   772  
   773  err := viper.Unmarshal(&C)
   774  if err != nil {
   775  	t.Fatalf("unable to decode into struct, %v", err)
   776  }
   777  ```
   778  
   779  Viper uses [github.com/mitchellh/mapstructure](https://github.com/mitchellh/mapstructure) under the hood for unmarshaling values which uses `mapstructure` tags by default.
   780  
   781  ### Decoding custom formats
   782  
   783  A frequently requested feature for Viper is adding more value formats and decoders.
   784  For example, parsing character (dot, comma, semicolon, etc) separated strings into slices.
   785  
   786  This is already available in Viper using mapstructure decode hooks.
   787  
   788  Read more about the details in [this blog post](https://sagikazarmark.hu/blog/decoding-custom-formats-with-viper/).
   789  
   790  ### Marshalling to string
   791  
   792  You may need to marshal all the settings held in viper into a string rather than write them to a file.
   793  You can use your favorite format's marshaller with the config returned by `AllSettings()`.
   794  
   795  ```go
   796  import (
   797  	yaml "gopkg.in/yaml.v2"
   798  	// ...
   799  )
   800  
   801  func yamlStringSettings() string {
   802  	c := viper.AllSettings()
   803  	bs, err := yaml.Marshal(c)
   804  	if err != nil {
   805  		log.Fatalf("unable to marshal config to YAML: %v", err)
   806  	}
   807  	return string(bs)
   808  }
   809  ```
   810  
   811  ## Viper or Vipers?
   812  
   813  Viper comes ready to use out of the box. There is no configuration or
   814  initialization needed to begin using Viper. Since most applications will want
   815  to use a single central repository for their configuration, the viper package
   816  provides this. It is similar to a singleton.
   817  
   818  In all of the examples above, they demonstrate using viper in its singleton
   819  style approach.
   820  
   821  ### Working with multiple vipers
   822  
   823  You can also create many different vipers for use in your application. Each will
   824  have its own unique set of configurations and values. Each can read from a
   825  different config file, key value store, etc. All of the functions that viper
   826  package supports are mirrored as methods on a viper.
   827  
   828  Example:
   829  
   830  ```go
   831  x := viper.New()
   832  y := viper.New()
   833  
   834  x.SetDefault("ContentDir", "content")
   835  y.SetDefault("ContentDir", "foobar")
   836  
   837  //...
   838  ```
   839  
   840  When working with multiple vipers, it is up to the user to keep track of the
   841  different vipers.
   842  
   843  
   844  ## Q & A
   845  
   846  ### Why is it called “Viper”?
   847  
   848  A: Viper is designed to be a [companion](http://en.wikipedia.org/wiki/Viper_(G.I._Joe))
   849  to [Cobra](https://github.com/spf13/cobra). While both can operate completely
   850  independently, together they make a powerful pair to handle much of your
   851  application foundation needs.
   852  
   853  ### Why is it called “Cobra”?
   854  
   855  Is there a better name for a [commander](http://en.wikipedia.org/wiki/Cobra_Commander)?
   856  
   857  ### Does Viper support case sensitive keys?
   858  
   859  **tl;dr:** No.
   860  
   861  Viper merges configuration from various sources, many of which are either case insensitive or uses different casing than the rest of the sources (eg. env vars).
   862  In order to provide the best experience when using multiple sources, the decision has been made to make all keys case insensitive.
   863  
   864  There has been several attempts to implement case sensitivity, but unfortunately it's not that trivial. We might take a stab at implementing it in [Viper v2](https://github.com/spf13/viper/issues/772), but despite the initial noise, it does not seem to be requested that much.
   865  
   866  You can vote for case sensitivity by filling out this feedback form: https://forms.gle/R6faU74qPRPAzchZ9
   867  
   868  ### Is it safe to concurrently read and write to a viper?
   869  
   870  No, you will need to synchronize access to the viper yourself (for example by using the `sync` package). Concurrent reads and writes can cause a panic.
   871  
   872  ## Troubleshooting
   873  
   874  See [TROUBLESHOOTING.md](TROUBLESHOOTING.md).