vendor/github.com/spf13/viper/README.md
changeset 260 445e01aede7e
parent 256 6d9efbef00a9
child 262 8d3354485fc3
equal deleted inserted replaced
259:db4911b0c721 260:445e01aede7e
     9 [![run on repl.it](https://repl.it/badge/github/sagikazarmark/Viper-example)](https://repl.it/@sagikazarmark/Viper-example#main.go)
     9 [![run on repl.it](https://repl.it/badge/github/sagikazarmark/Viper-example)](https://repl.it/@sagikazarmark/Viper-example#main.go)
    10 
    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)
    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)
    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)
    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.14-61CFDD.svg?style=flat-square)
    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)
    15 [![PkgGoDev](https://pkg.go.dev/badge/mod/github.com/spf13/viper)](https://pkg.go.dev/mod/github.com/spf13/viper)
    16 
    16 
    17 **Go configuration with fangs!**
    17 **Go configuration with fangs!**
    18 
    18 
    19 Many Go projects are built using Viper including:
    19 Many Go projects are built using Viper including:
   125 
   125 
   126 You can handle the specific case where no config file is found like this:
   126 You can handle the specific case where no config file is found like this:
   127 
   127 
   128 ```go
   128 ```go
   129 if err := viper.ReadInConfig(); err != nil {
   129 if err := viper.ReadInConfig(); err != nil {
   130     if _, ok := err.(viper.ConfigFileNotFoundError); ok {
   130 	if _, ok := err.(viper.ConfigFileNotFoundError); ok {
   131         // Config file not found; ignore error if desired
   131 		// Config file not found; ignore error if desired
   132     } else {
   132 	} else {
   133         // Config file was found but another error was produced
   133 		// Config file was found but another error was produced
   134     }
   134 	}
   135 }
   135 }
   136 
   136 
   137 // Config file found and successfully parsed
   137 // Config file found and successfully parsed
   138 ```
   138 ```
   139 
   139 
   173 Optionally you can provide a function for Viper to run each time a change occurs.
   173 Optionally you can provide a function for Viper to run each time a change occurs.
   174 
   174 
   175 **Make sure you add all of the configPaths prior to calling `WatchConfig()`**
   175 **Make sure you add all of the configPaths prior to calling `WatchConfig()`**
   176 
   176 
   177 ```go
   177 ```go
   178 viper.WatchConfig()
       
   179 viper.OnConfigChange(func(e fsnotify.Event) {
   178 viper.OnConfigChange(func(e fsnotify.Event) {
   180 	fmt.Println("Config file changed:", e.Name)
   179 	fmt.Println("Config file changed:", e.Name)
   181 })
   180 })
       
   181 viper.WatchConfig()
   182 ```
   182 ```
   183 
   183 
   184 ### Reading Config from io.Reader
   184 ### Reading Config from io.Reader
   185 
   185 
   186 Viper predefines many configuration sources such as files, environment
   186 Viper predefines many configuration sources such as files, environment
   352 	pflag.Parse()
   352 	pflag.Parse()
   353 	viper.BindPFlags(pflag.CommandLine)
   353 	viper.BindPFlags(pflag.CommandLine)
   354 
   354 
   355 	i := viper.GetInt("flagname") // retrieve value from viper
   355 	i := viper.GetInt("flagname") // retrieve value from viper
   356 
   356 
   357 	...
   357 	// ...
   358 }
   358 }
   359 ```
   359 ```
   360 
   360 
   361 #### Flag interfaces
   361 #### Flag interfaces
   362 
   362 
   501 runtime_viper.Unmarshal(&runtime_conf)
   501 runtime_viper.Unmarshal(&runtime_conf)
   502 
   502 
   503 // open a goroutine to watch remote changes forever
   503 // open a goroutine to watch remote changes forever
   504 go func(){
   504 go func(){
   505 	for {
   505 	for {
   506 	    time.Sleep(time.Second * 5) // delay after each request
   506 		time.Sleep(time.Second * 5) // delay after each request
   507 
   507 
   508 	    // currently, only tested with etcd support
   508 		// currently, only tested with etcd support
   509 	    err := runtime_viper.WatchRemoteConfig()
   509 		err := runtime_viper.WatchRemoteConfig()
   510 	    if err != nil {
   510 		if err != nil {
   511 	        log.Errorf("unable to read remote config: %v", err)
   511 			log.Errorf("unable to read remote config: %v", err)
   512 	        continue
   512 			continue
   513 	    }
   513 		}
   514 
   514 
   515 	    // unmarshal new config into our runtime config struct. you can also use channel
   515 		// unmarshal new config into our runtime config struct. you can also use channel
   516 	    // to implement a signal to notify the system of the changes
   516 		// to implement a signal to notify the system of the changes
   517 	    runtime_viper.Unmarshal(&runtime_conf)
   517 		runtime_viper.Unmarshal(&runtime_conf)
   518 	}
   518 	}
   519 }()
   519 }()
   520 ```
   520 ```
   521 
   521 
   522 ## Getting Values From Viper
   522 ## Getting Values From Viper
   544 
   544 
   545 Example:
   545 Example:
   546 ```go
   546 ```go
   547 viper.GetString("logfile") // case-insensitive Setting & Getting
   547 viper.GetString("logfile") // case-insensitive Setting & Getting
   548 if viper.GetBool("verbose") {
   548 if viper.GetBool("verbose") {
   549     fmt.Println("verbose enabled")
   549 	fmt.Println("verbose enabled")
   550 }
   550 }
   551 ```
   551 ```
   552 ### Accessing nested keys
   552 ### Accessing nested keys
   553 
   553 
   554 The accessor methods also accept formatted paths to deeply nested keys. For
   554 The accessor methods also accept formatted paths to deeply nested keys. For
   667 So instead of doing that let's pass a Viper instance to the constructor that represents a subset of the configuration:
   667 So instead of doing that let's pass a Viper instance to the constructor that represents a subset of the configuration:
   668 
   668 
   669 ```go
   669 ```go
   670 cache1Config := viper.Sub("cache.cache1")
   670 cache1Config := viper.Sub("cache.cache1")
   671 if cache1Config == nil { // Sub returns nil if the key cannot be found
   671 if cache1Config == nil { // Sub returns nil if the key cannot be found
   672     panic("cache configuration not found")
   672 	panic("cache configuration not found")
   673 }
   673 }
   674 
   674 
   675 cache1 := NewCache(cache1Config)
   675 cache1 := NewCache(cache1Config)
   676 ```
   676 ```
   677 
   677 
   679 
   679 
   680 Internally, the `NewCache` function can address `max-items` and `item-size` keys directly:
   680 Internally, the `NewCache` function can address `max-items` and `item-size` keys directly:
   681 
   681 
   682 ```go
   682 ```go
   683 func NewCache(v *Viper) *Cache {
   683 func NewCache(v *Viper) *Cache {
   684     return &Cache{
   684 	return &Cache{
   685         MaxItems: v.GetInt("max-items"),
   685 		MaxItems: v.GetInt("max-items"),
   686         ItemSize: v.GetInt("item-size"),
   686 		ItemSize: v.GetInt("item-size"),
   687     }
   687 	}
   688 }
   688 }
   689 ```
   689 ```
   690 
   690 
   691 The resulting code is easy to test, since it's decoupled from the main config structure,
   691 The resulting code is easy to test, since it's decoupled from the main config structure,
   692 and easier to reuse (for the same reason).
   692 and easier to reuse (for the same reason).
   724 
   724 
   725 ```go
   725 ```go
   726 v := viper.NewWithOptions(viper.KeyDelimiter("::"))
   726 v := viper.NewWithOptions(viper.KeyDelimiter("::"))
   727 
   727 
   728 v.SetDefault("chart::values", map[string]interface{}{
   728 v.SetDefault("chart::values", map[string]interface{}{
   729     "ingress": map[string]interface{}{
   729 	"ingress": map[string]interface{}{
   730         "annotations": map[string]interface{}{
   730 		"annotations": map[string]interface{}{
   731             "traefik.frontend.rule.type":                 "PathPrefix",
   731 			"traefik.frontend.rule.type":                 "PathPrefix",
   732             "traefik.ingress.kubernetes.io/ssl-redirect": "true",
   732 			"traefik.ingress.kubernetes.io/ssl-redirect": "true",
   733         },
   733 		},
   734     },
   734 	},
   735 })
   735 })
   736 
   736 
   737 type config struct {
   737 type config struct {
   738 	Chart struct{
   738 	Chart struct{
   739         Values map[string]interface{}
   739 		Values map[string]interface{}
   740     }
   740 	}
   741 }
   741 }
   742 
   742 
   743 var C config
   743 var C config
   744 
   744 
   745 v.Unmarshal(&C)
   745 v.Unmarshal(&C)
   776 }
   776 }
   777 ```
   777 ```
   778 
   778 
   779 Viper uses [github.com/mitchellh/mapstructure](https://github.com/mitchellh/mapstructure) under the hood for unmarshaling values which uses `mapstructure` tags by default.
   779 Viper uses [github.com/mitchellh/mapstructure](https://github.com/mitchellh/mapstructure) under the hood for unmarshaling values which uses `mapstructure` tags by default.
   780 
   780 
       
   781 ### Decoding custom formats
       
   782 
       
   783 A frequently requested feature for Viper is adding more value formats and decoders.
       
   784 For example, parsing character (dot, comma, semicolon, etc) separated strings into slices.
       
   785 
       
   786 This is already available in Viper using mapstructure decode hooks.
       
   787 
       
   788 Read more about the details in [this blog post](https://sagikazarmark.hu/blog/decoding-custom-formats-with-viper/).
       
   789 
   781 ### Marshalling to string
   790 ### Marshalling to string
   782 
   791 
   783 You may need to marshal all the settings held in viper into a string rather than write them to a file.
   792 You may need to marshal all the settings held in viper into a string rather than write them to a file.
   784 You can use your favorite format's marshaller with the config returned by `AllSettings()`.
   793 You can use your favorite format's marshaller with the config returned by `AllSettings()`.
   785 
   794 
   786 ```go
   795 ```go
   787 import (
   796 import (
   788     yaml "gopkg.in/yaml.v2"
   797 	yaml "gopkg.in/yaml.v2"
   789     // ...
   798 	// ...
   790 )
   799 )
   791 
   800 
   792 func yamlStringSettings() string {
   801 func yamlStringSettings() string {
   793     c := viper.AllSettings()
   802 	c := viper.AllSettings()
   794     bs, err := yaml.Marshal(c)
   803 	bs, err := yaml.Marshal(c)
   795     if err != nil {
   804 	if err != nil {
   796         log.Fatalf("unable to marshal config to YAML: %v", err)
   805 		log.Fatalf("unable to marshal config to YAML: %v", err)
   797     }
   806 	}
   798     return string(bs)
   807 	return string(bs)
   799 }
   808 }
   800 ```
   809 ```
   801 
   810 
   802 ## Viper or Vipers?
   811 ## Viper or Vipers?
   803 
   812