blob: cad242d1b062c5548fcda332be7bc1b6ab723388 [file] [log] [blame] [view]
Steve Franciad2f75b42015-11-02 11:07:43 -05001![viper logo](https://cloud.githubusercontent.com/assets/173412/10886745/998df88a-8151-11e5-9448-4736db51020d.png)
Steve Franciaf98d9bf2014-04-02 07:33:33 -07002
Steve Franciad2f75b42015-11-02 11:07:43 -05003Go configuration with fangs!
The Gitter Badger2763b902015-05-01 20:02:50 +00004
Steve Franciadd66c892016-02-08 17:01:43 -05005Many 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* [DOIt](https://github.com/bryanl/doit)
14
Steve Franciad2f75b42015-11-02 11:07:43 -050015 [![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)
16
spf13a54c4152014-04-05 15:44:26 -040017
18## What is Viper?
19
Steve Franciad2f75b42015-11-02 11:07:43 -050020Viper is a complete configuration solution for go applications including 12 factor apps. It is designed
jackspirou2abb1be2015-07-19 12:52:04 -050021to work within an application, and can handle all types of configuration needs
22and formats. It supports:
spf13cacbc4c2014-12-07 02:03:49 +010023
24* setting defaults
ryanwalls30ce4442016-01-30 11:44:53 -070025* reading from JSON, TOML, YAML, HCL, and Java properties config files
spf13e37b56e2015-11-09 23:22:04 -050026* live watching and re-reading of config files (optional)
spf13cacbc4c2014-12-07 02:03:49 +010027* reading from environment variables
Jonathan Boullece085322015-11-25 11:51:57 -080028* reading from remote config systems (etcd or Consul), and watching changes
spf13cacbc4c2014-12-07 02:03:49 +010029* reading from command line flags
oliveagle2a7f7f42015-05-11 12:33:35 +080030* reading from buffer
spf13cacbc4c2014-12-07 02:03:49 +010031* setting explicit values
32
jackspirou2abb1be2015-07-19 12:52:04 -050033Viper can be thought of as a registry for all of your applications
spf13cacbc4c2014-12-07 02:03:49 +010034configuration needs.
spf13a54c4152014-04-05 15:44:26 -040035
36## Why Viper?
37
jackspirou2abb1be2015-07-19 12:52:04 -050038When building a modern application, you don’t want to worry about
Anthony Fok0c5f3e22015-03-07 03:52:13 -070039configuration file formats; you want to focus on building awesome software.
spf13a54c4152014-04-05 15:44:26 -040040Viper is here to help with that.
41
42Viper does the following for you:
43
ryanwalls30ce4442016-01-30 11:44:53 -0700441. Find, load, and unmarshal a configuration file in JSON, TOML, YAML, HCL, or Java properties formats.
spf13cacbc4c2014-12-07 02:03:49 +0100452. Provide a mechanism to set default values for your different
Anthony Fok0c5f3e22015-03-07 03:52:13 -070046 configuration options.
jackspirou2abb1be2015-07-19 12:52:04 -0500473. Provide a mechanism to set override values for options specified through
48 command line flags.
494. Provide an alias system to easily rename parameters without breaking existing
50 code.
515. Make it easy to tell the difference between when a user has provided a
52 command line or config file which is the same as the default.
spf13a54c4152014-04-05 15:44:26 -040053
jackspirou2abb1be2015-07-19 12:52:04 -050054Viper uses the following precedence order. Each item takes precedence over the
55item below it:
spf13a54c4152014-04-05 15:44:26 -040056
spf13cacbc4c2014-12-07 02:03:49 +010057 * explicit call to Set
58 * flag
59 * env
60 * config
61 * key/value store
62 * default
spf13a54c4152014-04-05 15:44:26 -040063
64Viper configuration keys are case insensitive.
65
spf1354fed162014-12-22 21:45:56 -050066## Putting Values into Viper
spf13a54c4152014-04-05 15:44:26 -040067
spf13cacbc4c2014-12-07 02:03:49 +010068### Establishing Defaults
69
jackspirou2abb1be2015-07-19 12:52:04 -050070A good configuration system will support default values. A default value is not
Derek Parkercc3dd552015-12-03 11:47:09 -080071required for a key, but it's useful in the event that a key hasn’t been set via
jackspirou2abb1be2015-07-19 12:52:04 -050072config file, environment variable, remote configuration or flag.
spf13cacbc4c2014-12-07 02:03:49 +010073
74Examples:
75
Maxime Horcholle1e6a2372015-07-16 14:16:31 +020076```go
77viper.SetDefault("ContentDir", "content")
78viper.SetDefault("LayoutDir", "layouts")
79viper.SetDefault("Taxonomies", map[string]string{"tag": "tags", "category": "categories"})
80```
spf13cacbc4c2014-12-07 02:03:49 +010081
82### Reading Config Files
83
jackspirou2abb1be2015-07-19 12:52:04 -050084Viper requires minimal configuration so it knows where to look for config files.
ryanwalls30ce4442016-01-30 11:44:53 -070085Viper supports JSON, TOML, YAML, HCL, and Java Properties files. Viper can search multiple paths, but
jackspirou2abb1be2015-07-19 12:52:04 -050086currently a single Viper instance only supports a single configuration file.
Vlad Didenkoa7ef0202015-11-06 13:43:15 -060087Viper does not default to any configuration search paths leaving defaults decision
88to an application.
89
90Here is an example of how to use Viper to search for and read a configuration file.
91None of the specific paths are required, but at least one path should be provided
spf13e37b56e2015-11-09 23:22:04 -050092where a configuration file is expected.
spf13a54c4152014-04-05 15:44:26 -040093
Maxime Horcholle1e6a2372015-07-16 14:16:31 +020094```go
95viper.SetConfigName("config") // name of config file (without extension)
96viper.AddConfigPath("/etc/appname/") // path to look for the config file in
97viper.AddConfigPath("$HOME/.appname") // call multiple times to add many search paths
Vlad Didenkoa7ef0202015-11-06 13:43:15 -060098viper.AddConfigPath(".") // optionally look for config in the working directory
Maxime Horcholle1e6a2372015-07-16 14:16:31 +020099err := viper.ReadInConfig() // Find and read the config file
100if err != nil { // Handle errors reading the config file
101 panic(fmt.Errorf("Fatal error config file: %s \n", err))
102}
103```
spf13a54c4152014-04-05 15:44:26 -0400104
spf13e37b56e2015-11-09 23:22:04 -0500105### Watching and re-reading config files
106
107Viper supports the ability to have your application live read a config file while running.
108
109Gone are the days of needing to restart a server to have a config take effect,
110viper powered applications can read an update to a config file while running and
111not miss a beat.
112
113Simply tell the viper instance to watchConfig.
114Optionally you can provide a function for Viper to run each time a change occurs.
115
116**Make sure you add all of the configPaths prior to calling `WatchConfig()`**
117
118```go
119 viper.WatchConfig()
120 viper.OnConfigChange(func(e fsnotify.Event) {
121 fmt.Println("Config file changed:", e.Name)
122 })
123```
124
oliveagle0d75ece2015-05-15 19:36:05 +0800125### Reading Config from io.Reader
oliveagle2a7f7f42015-05-11 12:33:35 +0800126
jackspirou2abb1be2015-07-19 12:52:04 -0500127Viper predefines many configuration sources such as files, environment
128variables, flags, and remote K/V store, but you are not bound to them. You can
129also implement your own required configuration source and feed it to viper.
oliveagle2a7f7f42015-05-11 12:33:35 +0800130
Maxime Horcholle1e6a2372015-07-16 14:16:31 +0200131```go
oliveagle2a7f7f42015-05-11 12:33:35 +0800132viper.SetConfigType("yaml") // or viper.SetConfigType("YAML")
133
jackspirou2abb1be2015-07-19 12:52:04 -0500134// any approach to require this configuration into your program.
oliveagle2a7f7f42015-05-11 12:33:35 +0800135var yamlExample = []byte(`
136Hacker: true
137name: steve
138hobbies:
139- skateboarding
140- snowboarding
141- go
142clothing:
143 jacket: leather
144 trousers: denim
145age: 35
146eyes : brown
147beard: true
148`)
149
oliveagle0d75ece2015-05-15 19:36:05 +0800150viper.ReadConfig(bytes.NewBuffer(yamlExample))
oliveagle2a7f7f42015-05-11 12:33:35 +0800151
152viper.Get("name") // this would be "steve"
Maxime Horcholle1e6a2372015-07-16 14:16:31 +0200153```
oliveagle2a7f7f42015-05-11 12:33:35 +0800154
spf13a54c4152014-04-05 15:44:26 -0400155### Setting Overrides
156
spf13cacbc4c2014-12-07 02:03:49 +0100157These could be from a command line flag, or from your own application logic.
158
Maxime Horcholle1e6a2372015-07-16 14:16:31 +0200159```go
160viper.Set("Verbose", true)
161viper.Set("LogFile", LogFile)
162```
spf13a54c4152014-04-05 15:44:26 -0400163
164### Registering and Using Aliases
165
spf13cacbc4c2014-12-07 02:03:49 +0100166Aliases permit a single value to be referenced by multiple keys
167
Maxime Horcholle1e6a2372015-07-16 14:16:31 +0200168```go
169viper.RegisterAlias("loud", "Verbose")
spf13a54c4152014-04-05 15:44:26 -0400170
Maxime Horcholle1e6a2372015-07-16 14:16:31 +0200171viper.Set("verbose", true) // same result as next line
172viper.Set("loud", true) // same result as prior line
spf13a54c4152014-04-05 15:44:26 -0400173
Maxime Horcholle1e6a2372015-07-16 14:16:31 +0200174viper.GetBool("loud") // true
175viper.GetBool("verbose") // true
176```
spf13a54c4152014-04-05 15:44:26 -0400177
spf13cacbc4c2014-12-07 02:03:49 +0100178### Working with Environment Variables
179
180Viper has full support for environment variables. This enables 12 factor
jackspirou2abb1be2015-07-19 12:52:04 -0500181applications out of the box. There are four methods that exist to aid working
182with ENV:
spf13cacbc4c2014-12-07 02:03:49 +0100183
jackspirou2abb1be2015-07-19 12:52:04 -0500184 * `AutomaticEnv()`
185 * `BindEnv(string...) : error`
186 * `SetEnvPrefix(string)`
187 * `SetEnvReplacer(string...) *strings.Replacer`
spf13cacbc4c2014-12-07 02:03:49 +0100188
Anthony Fok0c5f3e22015-03-07 03:52:13 -0700189_When working with ENV variables, it’s important to recognize that Viper
spf1354fed162014-12-22 21:45:56 -0500190treats ENV variables as case sensitive._
191
jackspirou2abb1be2015-07-19 12:52:04 -0500192Viper provides a mechanism to try to ensure that ENV variables are unique. By
193using `SetEnvPrefix`, you can tell Viper to use add a prefix while reading from
194the environment variables. Both `BindEnv` and `AutomaticEnv` will use this
195prefix.
spf13cacbc4c2014-12-07 02:03:49 +0100196
jackspirou2abb1be2015-07-19 12:52:04 -0500197`BindEnv` takes one or two parameters. The first parameter is the key name, the
198second is the name of the environment variable. The name of the environment
199variable is case sensitive. If the ENV variable name is not provided, then
200Viper will automatically assume that the key name matches the ENV variable name,
201but the ENV variable is IN ALL CAPS. When you explicitly provide the ENV
202variable name, it **does not** automatically add the prefix.
spf13cacbc4c2014-12-07 02:03:49 +0100203
jackspirou2abb1be2015-07-19 12:52:04 -0500204One important thing to recognize when working with ENV variables is that the
205value will be read each time it is accessed. Viper does not fix the value when
206the `BindEnv` is called.
spf13cacbc4c2014-12-07 02:03:49 +0100207
jackspirou2abb1be2015-07-19 12:52:04 -0500208`AutomaticEnv` is a powerful helper especially when combined with
209`SetEnvPrefix`. When called, Viper will check for an environment variable any
210time a `viper.Get` request is made. It will apply the following rules. It will
211check for a environment variable with a name matching the key uppercased and
212prefixed with the `EnvPrefix` if set.
spf13cacbc4c2014-12-07 02:03:49 +0100213
jackspirou2abb1be2015-07-19 12:52:04 -0500214`SetEnvReplacer` allows you to use a `strings.Replacer` object to rewrite Env
215keys to an extent. This is useful if you want to use `-` or something in your
216`Get()` calls, but want your environmental variables to use `_` delimiters. An
217example of using it can be found in `viper_test.go`.
Chance Zibolski03fb74b2015-03-06 11:21:17 -0800218
spf1354fed162014-12-22 21:45:56 -0500219#### Env example
220
Maxime Horcholle1e6a2372015-07-16 14:16:31 +0200221```go
222SetEnvPrefix("spf") // will be uppercased automatically
223BindEnv("id")
spf1354fed162014-12-22 21:45:56 -0500224
Maxime Horcholle1e6a2372015-07-16 14:16:31 +0200225os.Setenv("SPF_ID", "13") // typically done outside of the app
spf1354fed162014-12-22 21:45:56 -0500226
Maxime Horcholle1e6a2372015-07-16 14:16:31 +0200227id := Get("id") // 13
228```
spf1354fed162014-12-22 21:45:56 -0500229
spf13cacbc4c2014-12-07 02:03:49 +0100230### Working with Flags
231
jackspirou2abb1be2015-07-19 12:52:04 -0500232Viper has the ability to bind to flags. Specifically, Viper supports `Pflags`
233as used in the [Cobra](https://github.com/spf13/cobra) library.
spf13cacbc4c2014-12-07 02:03:49 +0100234
jackspirou2abb1be2015-07-19 12:52:04 -0500235Like `BindEnv`, the value is not set when the binding method is called, but when
236it is accessed. This means you can bind as early as you want, even in an
237`init()` function.
spf13cacbc4c2014-12-07 02:03:49 +0100238
jackspirou2abb1be2015-07-19 12:52:04 -0500239The `BindPFlag()` method provides this functionality.
spf13cacbc4c2014-12-07 02:03:49 +0100240
241Example:
242
Maxime Horcholle1e6a2372015-07-16 14:16:31 +0200243```go
244serverCmd.Flags().Int("port", 1138, "Port to run Application server on")
245viper.BindPFlag("port", serverCmd.Flags().Lookup("port"))
246```
spf13cacbc4c2014-12-07 02:03:49 +0100247
Sanjay Bhandari5c53af52015-12-04 15:07:55 -0500248The use of [pflag](https://github.com/spf13/pflag/) in Viper does not preclude
249the use of other packages that use the [flag](https://golang.org/pkg/flag/)
250package from the standard library. The pflag package can handle the flags
251defined for the flag package by importing these flags. This is accomplished
252by a calling a convenience function provided by the pflag package called
253AddGoFlagSet().
254
255Example:
256
257```go
258package main
259
260import (
261 "flag"
262 "github.com/spf13/pflag"
263)
264
265func main() {
266 pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
267 pflag.Parse()
268 ...
269}
270```
271
David Calaverac8c63122015-12-18 18:34:45 -0500272#### Flag interfaces
273
274Viper provides two Go interfaces to bind other flag systems if you don't use `Pflags`.
275
276`FlagValue` represents a single flag. This is a very simple example on how to implement this interface:
277
278```go
279type myFlag struct {}
280func (f myFlag) IsChanged() { return false }
281func (f myFlag) Name() { return "my-flag-name" }
282func (f myFlag) ValueString() { return "my-flag-value" }
283func (f myFlag) ValueType() { return "string" }
284```
285
286Once your flag implements this interface, you can simply tell Viper to bind it:
287
288```go
289viper.BindFlagValue("my-flag-name", myFlag{})
290```
291
292`FlagValueSet` represents a group of flags. This is a very simple example on how to implement this interface:
293
294```go
295type myFlagSet struct {
296 flags []myFlag
297}
298
299func (f myFlagSet) VisitAll(fn func(FlagValue)) {
300 for _, flag := range flags {
301 fn(flag)
302 }
303}
304```
305
306Once your flag set implements this interface, you can simply tell Viper to bind it:
307
308```go
309fSet := myFlagSet{
310 flags: []myFlag{myFlag{}, myFlag{}},
311}
312viper.BindFlagValues("my-flags", fSet)
313```
314
Brian Ketelsen51da30f2014-10-27 15:32:46 -0400315### Remote Key/Value Store Support
bepbe5ff3e2015-05-30 21:28:33 +0200316
jackspirou2abb1be2015-07-19 12:52:04 -0500317To enable remote support in Viper, do a blank import of the `viper/remote`
318package:
bepbe5ff3e2015-05-30 21:28:33 +0200319
David Symonds493be7d2015-10-26 14:36:42 +1100320`import _ "github.com/spf13/viper/remote"`
bepbe5ff3e2015-05-30 21:28:33 +0200321
patdhlk79971f12015-12-13 21:47:41 +0100322Viper will read a config string (as JSON, TOML, YAML or HCL) retrieved from a path
Jonathan Boullece085322015-11-25 11:51:57 -0800323in a Key/Value store such as etcd or Consul. These values take precedence over
jackspirou2abb1be2015-07-19 12:52:04 -0500324default values, but are overridden by configuration values retrieved from disk,
Brian Ketelsen51da30f2014-10-27 15:32:46 -0400325flags, or environment variables.
326
jackspirou2abb1be2015-07-19 12:52:04 -0500327Viper uses [crypt](https://github.com/xordataexchange/crypt) to retrieve
328configuration from the K/V store, which means that you can store your
329configuration values encrypted and have them automatically decrypted if you have
330the correct gpg keyring. Encryption is optional.
Brian Ketelsen51da30f2014-10-27 15:32:46 -0400331
332You can use remote configuration in conjunction with local configuration, or
Chance Zibolski12583322015-03-06 11:21:50 -0800333independently of it.
Brian Ketelsen51da30f2014-10-27 15:32:46 -0400334
jackspirou2abb1be2015-07-19 12:52:04 -0500335`crypt` has a command-line helper that you can use to put configurations in your
336K/V store. `crypt` defaults to etcd on http://127.0.0.1:4001.
Brian Ketelsen51da30f2014-10-27 15:32:46 -0400337
Maxime Horcholle1e6a2372015-07-16 14:16:31 +0200338```bash
339$ go get github.com/xordataexchange/crypt/bin/crypt
340$ crypt set -plaintext /config/hugo.json /Users/hugo/settings/config.json
341```
Brian Ketelsen51da30f2014-10-27 15:32:46 -0400342
343Confirm that your value was set:
344
Maxime Horcholle1e6a2372015-07-16 14:16:31 +0200345```bash
346$ crypt get -plaintext /config/hugo.json
347```
Brian Ketelsen51da30f2014-10-27 15:32:46 -0400348
jackspirou2abb1be2015-07-19 12:52:04 -0500349See the `crypt` documentation for examples of how to set encrypted values, or
350how to use Consul.
Brian Ketelsen51da30f2014-10-27 15:32:46 -0400351
352### Remote Key/Value Store Example - Unencrypted
353
Maxime Horcholle1e6a2372015-07-16 14:16:31 +0200354```go
355viper.AddRemoteProvider("etcd", "http://127.0.0.1:4001","/config/hugo.json")
ryanwalls30ce4442016-01-30 11:44:53 -0700356viper.SetConfigType("json") // because there is no file extension in a stream of bytes, supported extensions are "json", "toml", "yaml", "yml", "properties", "props", "prop"
Maxime Horcholle1e6a2372015-07-16 14:16:31 +0200357err := viper.ReadRemoteConfig()
358```
Brian Ketelsen51da30f2014-10-27 15:32:46 -0400359
360### Remote Key/Value Store Example - Encrypted
361
Maxime Horcholle1e6a2372015-07-16 14:16:31 +0200362```go
363viper.AddSecureRemoteProvider("etcd","http://127.0.0.1:4001","/config/hugo.json","/etc/secrets/mykeyring.gpg")
ryanwalls30ce4442016-01-30 11:44:53 -0700364viper.SetConfigType("json") // because there is no file extension in a stream of bytes, supported extensions are "json", "toml", "yaml", "yml", "properties", "props", "prop"
Maxime Horcholle1e6a2372015-07-16 14:16:31 +0200365err := viper.ReadRemoteConfig()
366```
Brian Ketelsen51da30f2014-10-27 15:32:46 -0400367
Jonathan Boullece085322015-11-25 11:51:57 -0800368### Watching Changes in etcd - Unencrypted
oliveagle2a7f7f42015-05-11 12:33:35 +0800369
Maxime Horcholle1e6a2372015-07-16 14:16:31 +0200370```go
371// alternatively, you can create a new viper instance.
372var runtime_viper = viper.New()
oliveagle2a7f7f42015-05-11 12:33:35 +0800373
Maxime Horcholle1e6a2372015-07-16 14:16:31 +0200374runtime_viper.AddRemoteProvider("etcd", "http://127.0.0.1:4001", "/config/hugo.yml")
ryanwalls30ce4442016-01-30 11:44:53 -0700375runtime_viper.SetConfigType("yaml") // because there is no file extension in a stream of bytes, supported extensions are "json", "toml", "yaml", "yml", "properties", "props", "prop"
oliveagle2a7f7f42015-05-11 12:33:35 +0800376
Maxime Horcholle1e6a2372015-07-16 14:16:31 +0200377// read from remote config the first time.
378err := runtime_viper.ReadRemoteConfig()
oliveagle2a7f7f42015-05-11 12:33:35 +0800379
Matt Surabian1967d932015-08-23 23:40:56 -0400380// unmarshal config
381runtime_viper.Unmarshal(&runtime_conf)
oliveagle2a7f7f42015-05-11 12:33:35 +0800382
James Mintram3041a432015-10-22 16:25:52 +0100383// open a goroutine to watch remote changes forever
Maxime Horcholle1e6a2372015-07-16 14:16:31 +0200384go func(){
385 for {
386 time.Sleep(time.Second * 5) // delay after each request
spf13e37b56e2015-11-09 23:22:04 -0500387
James Mintram3041a432015-10-22 16:25:52 +0100388 // currently, only tested with etcd support
Maxime Horcholle1e6a2372015-07-16 14:16:31 +0200389 err := runtime_viper.WatchRemoteConfig()
390 if err != nil {
391 log.Errorf("unable to read remote config: %v", err)
392 continue
393 }
spf13e37b56e2015-11-09 23:22:04 -0500394
395 // unmarshal new config into our runtime config struct. you can also use channel
Maxime Horcholle1e6a2372015-07-16 14:16:31 +0200396 // to implement a signal to notify the system of the changes
Matt Surabian1967d932015-08-23 23:40:56 -0400397 runtime_viper.Unmarshal(&runtime_conf)
Maxime Horcholle1e6a2372015-07-16 14:16:31 +0200398 }
399}()
400```
Brian Ketelsen51da30f2014-10-27 15:32:46 -0400401
spf1354fed162014-12-22 21:45:56 -0500402## Getting Values From Viper
403
jackspirou2abb1be2015-07-19 12:52:04 -0500404In Viper, there are a few ways to get a value depending on the value's type.
Chance Zibolski12583322015-03-06 11:21:50 -0800405The following functions and methods exist:
spf1354fed162014-12-22 21:45:56 -0500406
jackspirou2abb1be2015-07-19 12:52:04 -0500407 * `Get(key string) : interface{}`
408 * `GetBool(key string) : bool`
409 * `GetFloat64(key string) : float64`
410 * `GetInt(key string) : int`
411 * `GetString(key string) : string`
412 * `GetStringMap(key string) : map[string]interface{}`
413 * `GetStringMapString(key string) : map[string]string`
414 * `GetStringSlice(key string) : []string`
415 * `GetTime(key string) : time.Time`
416 * `GetDuration(key string) : time.Duration`
417 * `IsSet(key string) : bool`
spf1354fed162014-12-22 21:45:56 -0500418
jackspirou2abb1be2015-07-19 12:52:04 -0500419One important thing to recognize is that each Get function will return a zero
420value if it’s not found. To check if a given key exists, the `IsSet()` method
421has been provided.
spf1354fed162014-12-22 21:45:56 -0500422
423Example:
Maxime Horcholle1e6a2372015-07-16 14:16:31 +0200424```go
425viper.GetString("logfile") // case-insensitive Setting & Getting
426if viper.GetBool("verbose") {
427 fmt.Println("verbose enabled")
428}
429```
Kiril Zvezdarov2e47d9e2015-05-02 14:20:33 -0400430### Accessing nested keys
431
jackspirou2abb1be2015-07-19 12:52:04 -0500432The accessor methods also accept formatted paths to deeply nested keys. For
433example, if the following JSON file is loaded:
Kiril Zvezdarov2e47d9e2015-05-02 14:20:33 -0400434
Maxime Horcholle1e6a2372015-07-16 14:16:31 +0200435```json
Kiril Zvezdarov2e47d9e2015-05-02 14:20:33 -0400436{
437 "host": {
438 "address": "localhost",
439 "port": 5799
440 },
441 "datastore": {
442 "metric": {
443 "host": "127.0.0.1",
444 "port": 3099
445 },
446 "warehouse": {
447 "host": "198.0.0.1",
448 "port": 2112
449 }
450 }
451}
452
453```
454
455Viper can access a nested field by passing a `.` delimited path of keys:
Maxime Horcholle1e6a2372015-07-16 14:16:31 +0200456
457```go
Kiril Zvezdarov2e47d9e2015-05-02 14:20:33 -0400458GetString("datastore.metric.host") // (returns "127.0.0.1")
459```
460
jackspirou2abb1be2015-07-19 12:52:04 -0500461This obeys the precedence rules established above; the search for the root key
462(in this example, `datastore`) will cascade through the remaining configuration
463registries until found. The search for the sub-keys (`metric` and `host`),
464however, will not.
Kiril Zvezdarov2e47d9e2015-05-02 14:20:33 -0400465
466For example, if the `metric` key was not defined in the configuration loaded
467from file, but was defined in the defaults, Viper would return the zero value.
468
jackspirou2abb1be2015-07-19 12:52:04 -0500469On the other hand, if the primary key was not defined, Viper would go through
470the remaining registries looking for it.
Kiril Zvezdarov2e47d9e2015-05-02 14:20:33 -0400471
jackspirou2abb1be2015-07-19 12:52:04 -0500472Lastly, if there exists a key that matches the delimited key path, its value
473will be returned instead. E.g.
Kiril Zvezdarov2e47d9e2015-05-02 14:20:33 -0400474
Maxime Horcholle1e6a2372015-07-16 14:16:31 +0200475```json
Kiril Zvezdarov2e47d9e2015-05-02 14:20:33 -0400476{
477 "datastore.metric.host": "0.0.0.0",
478 "host": {
479 "address": "localhost",
480 "port": 5799
481 },
482 "datastore": {
483 "metric": {
484 "host": "127.0.0.1",
485 "port": 3099
486 },
487 "warehouse": {
488 "host": "198.0.0.1",
489 "port": 2112
490 }
491 }
492}
493
494GetString("datastore.metric.host") //returns "0.0.0.0"
495```
496
Lei Feng105e3d02015-12-24 19:44:44 +0800497### Extract sub-tree
498
499Extract sub-tree from Viper.
500
501For example, `viper` represents:
502
503```json
504app:
505 cache1:
506 max-items: 100
507 item-size: 64
508 cache2:
509 max-items: 200
510 item-size: 80
511```
512
513After executing:
514
515```go
516subv := viper.Sub("app.cache1")
517```
518
519`subv` represents:
520
521```json
522max-items: 100
523item-size: 64
524```
525
526Suppose we have:
527
528```go
529func NewCache(cfg *Viper) *Cache {...}
530```
531
532which creates a cache based on config information formatted as `subv`.
533Now it's easy to create these 2 caches separately as:
534
535```go
536cfg1 := viper.Sub("app.cache1")
537cache1 := NewCache(cfg1)
538
539cfg2 := viper.Sub("app.cache2")
540cache2 := NewCache(cfg2)
541```
542
Matt Surabian1967d932015-08-23 23:40:56 -0400543### Unmarshaling
spf1354fed162014-12-22 21:45:56 -0500544
Matt Surabian1967d932015-08-23 23:40:56 -0400545You also have the option of Unmarshaling all or a specific value to a struct, map,
jackspirou2abb1be2015-07-19 12:52:04 -0500546etc.
spf1354fed162014-12-22 21:45:56 -0500547
548There are two methods to do this:
549
Matt Surabian1967d932015-08-23 23:40:56 -0400550 * `Unmarshal(rawVal interface{}) : error`
551 * `UnmarshalKey(key string, rawVal interface{}) : error`
spf1354fed162014-12-22 21:45:56 -0500552
553Example:
554
Maxime Horcholle1e6a2372015-07-16 14:16:31 +0200555```go
556type config struct {
557 Port int
558 Name string
Abhinandan823bc132015-12-03 21:44:42 +0530559 PathMap string `mapstructure:"path_map"`
Maxime Horcholle1e6a2372015-07-16 14:16:31 +0200560}
spf1354fed162014-12-22 21:45:56 -0500561
Maxime Horcholle1e6a2372015-07-16 14:16:31 +0200562var C config
spf1354fed162014-12-22 21:45:56 -0500563
Matt Surabian1967d932015-08-23 23:40:56 -0400564err := Unmarshal(&C)
Maxime Horcholle1e6a2372015-07-16 14:16:31 +0200565if err != nil {
566 t.Fatalf("unable to decode into struct, %v", err)
567}
568```
spf1354fed162014-12-22 21:45:56 -0500569
570## Viper or Vipers?
spf13cacbc4c2014-12-07 02:03:49 +0100571
572Viper comes ready to use out of the box. There is no configuration or
jackspirou2abb1be2015-07-19 12:52:04 -0500573initialization needed to begin using Viper. Since most applications will want
574to use a single central repository for their configuration, the viper package
575provides this. It is similar to a singleton.
spf13cacbc4c2014-12-07 02:03:49 +0100576
jackspirou2abb1be2015-07-19 12:52:04 -0500577In all of the examples above, they demonstrate using viper in it's singleton
578style approach.
spf13cacbc4c2014-12-07 02:03:49 +0100579
580### Working with multiple vipers
581
jackspirou2abb1be2015-07-19 12:52:04 -0500582You can also create many different vipers for use in your application. Each will
583have it’s own unique set of configurations and values. Each can read from a
584different config file, key value store, etc. All of the functions that viper
585package supports are mirrored as methods on a viper.
spf13cacbc4c2014-12-07 02:03:49 +0100586
587Example:
588
Maxime Horcholle1e6a2372015-07-16 14:16:31 +0200589```go
590x := viper.New()
591y := viper.New()
spf13cacbc4c2014-12-07 02:03:49 +0100592
Maxime Horcholle1e6a2372015-07-16 14:16:31 +0200593x.SetDefault("ContentDir", "content")
594y.SetDefault("ContentDir", "foobar")
spf13cacbc4c2014-12-07 02:03:49 +0100595
Maxime Horcholle1e6a2372015-07-16 14:16:31 +0200596//...
597```
spf13cacbc4c2014-12-07 02:03:49 +0100598
jackspirou2abb1be2015-07-19 12:52:04 -0500599When working with multiple vipers, it is up to the user to keep track of the
600different vipers.
spf13a54c4152014-04-05 15:44:26 -0400601
602## Q & A
603
604Q: Why not INI files?
605
Anthony Fok0c5f3e22015-03-07 03:52:13 -0700606A: Ini files are pretty awful. There’s no standard format, and they are hard to
607validate. Viper is designed to work with JSON, TOML or YAML files. If someone
jackspirou2abb1be2015-07-19 12:52:04 -0500608really wants to add this feature, I’d be happy to merge it. It’s easy to specify
609which formats your application will permit.
spf13a54c4152014-04-05 15:44:26 -0400610
Anthony Fok0c5f3e22015-03-07 03:52:13 -0700611Q: Why is it called “Viper”?
spf13a54c4152014-04-05 15:44:26 -0400612
jackspirou2abb1be2015-07-19 12:52:04 -0500613A: Viper is designed to be a [companion](http://en.wikipedia.org/wiki/Viper_(G.I._Joe))
614to [Cobra](https://github.com/spf13/cobra). While both can operate completely
spf13a54c4152014-04-05 15:44:26 -0400615independently, together they make a powerful pair to handle much of your
616application foundation needs.
617
Anthony Fok0c5f3e22015-03-07 03:52:13 -0700618Q: Why is it called “Cobra”?
spf13a54c4152014-04-05 15:44:26 -0400619
Anthony Fok0c5f3e22015-03-07 03:52:13 -0700620A: Is there a better name for a [commander](http://en.wikipedia.org/wiki/Cobra_Commander)?