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