Merge branch 'master' into touchUpComments

This commit is contained in:
Anthony Fok 2017-07-22 23:36:39 -06:00 committed by GitHub
commit c65884f17a
2 changed files with 54 additions and 32 deletions

View file

@ -6,7 +6,7 @@ Many Go projects are built using Viper including:
* [Hugo](http://gohugo.io)
* [EMC RexRay](http://rexray.readthedocs.org/en/stable/)
* [Imgur's Incus](https://github.com/Imgur/incus)
* [Imgurs Incus](https://github.com/Imgur/incus)
* [Nanobox](https://github.com/nanobox-io/nanobox)/[Nanopack](https://github.com/nanopack)
* [Docker Notary](https://github.com/docker/Notary)
* [BloomApi](https://www.bloomapi.com/)
@ -17,7 +17,7 @@ Many Go projects are built using Viper including:
## What is Viper?
Viper is a complete configuration solution for go applications including 12 factor apps. It is designed
Viper is a complete configuration solution for Go applications including 12-Factor apps. It is designed
to work within an application, and can handle all types of configuration needs
and formats. It supports:
@ -68,7 +68,7 @@ Viper configuration keys are case insensitive.
### Establishing Defaults
A good configuration system will support default values. A default value is not
required for a key, but it's useful in the event that a key hasnt been set via
required for a key, but its useful in the event that a key hasnt been set via
config file, environment variable, remote configuration or flag.
Examples:
@ -116,10 +116,10 @@ Optionally you can provide a function for Viper to run each time a change occurs
**Make sure you add all of the configPaths prior to calling `WatchConfig()`**
```go
viper.WatchConfig()
viper.OnConfigChange(func(e fsnotify.Event) {
fmt.Println("Config file changed:", e.Name)
})
viper.WatchConfig()
viper.OnConfigChange(func(e fsnotify.Event) {
fmt.Println("Config file changed:", e.Name)
})
```
### Reading Config from io.Reader
@ -236,7 +236,7 @@ Like `BindEnv`, the value is not set when the binding method is called, but when
it is accessed. This means you can bind as early as you want, even in an
`init()` function.
The `BindPFlag()` method provides this functionality.
For individual flags, the `BindPFlag()` method provides this functionality.
Example:
@ -245,6 +245,19 @@ serverCmd.Flags().Int("port", 1138, "Port to run Application server on")
viper.BindPFlag("port", serverCmd.Flags().Lookup("port"))
```
You can also bind an existing set of pflags (pflag.FlagSet):
Example:
```go
pflag.Int("flagname", 1234, "help message for flagname")
pflag.Parse()
viper.BindPFlags(pflag.CommandLine)
i := viper.GetInt("flagname") // retrieve values from viper instead of pflag
```
The use of [pflag](https://github.com/spf13/pflag/) in Viper does not preclude
the use of other packages that use the [flag](https://golang.org/pkg/flag/)
package from the standard library. The pflag package can handle the flags
@ -263,15 +276,23 @@ import (
)
func main() {
// using standard library "flag" package
flag.Int("flagname", 1234, "help message for flagname")
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
pflag.Parse()
...
viper.BindPFlags(pflag.CommandLine)
i := viper.GetInt("flagname") // retrieve value from viper
...
}
```
#### Flag interfaces
Viper provides two Go interfaces to bind other flag systems if you don't use `Pflags`.
Viper provides two Go interfaces to bind other flag systems if you dont use `Pflags`.
`FlagValue` represents a single flag. This is a very simple example on how to implement this interface:
@ -401,7 +422,7 @@ go func(){
## Getting Values From Viper
In Viper, there are a few ways to get a value depending on the value's type.
In Viper, there are a few ways to get a value depending on the values type.
The following functions and methods exist:
* `Get(key string) : interface{}`
@ -531,7 +552,7 @@ func NewCache(cfg *Viper) *Cache {...}
```
which creates a cache based on config information formatted as `subv`.
Now it's easy to create these 2 caches separately as:
Now its easy to create these 2 caches separately as:
```go
cfg1 := viper.Sub("app.cache1")
@ -575,13 +596,13 @@ initialization needed to begin using Viper. Since most applications will want
to use a single central repository for their configuration, the viper package
provides this. It is similar to a singleton.
In all of the examples above, they demonstrate using viper in it's singleton
In all of the examples above, they demonstrate using viper in its singleton
style approach.
### Working with multiple vipers
You can also create many different vipers for use in your application. Each will
have its own unique set of configurations and values. Each can read from a
have its own unique set of configurations and values. Each can read from a
different config file, key value store, etc. All of the functions that viper
package supports are mirrored as methods on a viper.

View file

@ -53,7 +53,7 @@ func init() {
type remoteConfigFactory interface {
Get(rp RemoteProvider) (io.Reader, error)
Watch(rp RemoteProvider) (io.Reader, error)
WatchChannel(rp RemoteProvider)(<-chan *RemoteResponse, chan bool)
WatchChannel(rp RemoteProvider) (<-chan *RemoteResponse, chan bool)
}
// RemoteConfig is optional, see the remote package
@ -596,32 +596,33 @@ func (v *Viper) Get(key string) interface{} {
return nil
}
valType := val
if v.typeByDefValue {
// TODO(bep) this branch isn't covered by a single test.
valType := val
path := strings.Split(lcaseKey, v.keyDelim)
defVal := v.searchMap(v.defaults, path)
if defVal != nil {
valType = defVal
}
switch valType.(type) {
case bool:
return cast.ToBool(val)
case string:
return cast.ToString(val)
case int64, int32, int16, int8, int:
return cast.ToInt(val)
case float64, float32:
return cast.ToFloat64(val)
case time.Time:
return cast.ToTime(val)
case time.Duration:
return cast.ToDuration(val)
case []string:
return cast.ToStringSlice(val)
}
}
switch valType.(type) {
case bool:
return cast.ToBool(val)
case string:
return cast.ToString(val)
case int64, int32, int16, int8, int:
return cast.ToInt(val)
case float64, float32:
return cast.ToFloat64(val)
case time.Time:
return cast.ToTime(val)
case time.Duration:
return cast.ToDuration(val)
case []string:
return cast.ToStringSlice(val)
}
return val
}