github.com/byzk-project-deploy/viper@v0.0.0-20220810051311-c087119cd05b/README.md (about)

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