github.com/ava-labs/viper@v1.7.2-0.20210125155433-65cc0421b384/README.md (about)

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