github.com/intel-go/viper@v1.5.1-0.20191113170345-18a46e0e5e35/README.md (about)

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