github.com/kmhagan/viper@v1.6.3-0.20200410222425-d68b332001c2/README.md (about)

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