Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is the use of configuring the information processing framework Viper in Golang

2025-01-15 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article mainly introduces the Golang configuration information processing framework Viper what is useful, the article introduces in great detail, has a certain reference value, interested friends must read it!

Viper

Project address: https://github.com/spf13/viper

This article is translated from the README.md file in the project.

There are many Go language projects that use the Viper framework, such as:

Hugo

EMC RexRay

Imgur's Incus

Nanobox/Nanopack

Docker Notary

BloomApi

Doctl

Clairctl

What is Viper?

Viper is a library that facilitates Go language applications to process configuration information. It can handle configurations in multiple formats. The features it supports:

Set default value

Read configuration data from JSON, TOML, YAML, HCL, and Java properties files

Can monitor changes to the configuration file and reread the configuration file

Read configuration data from environment variables

Read data from the remote configuration system and monitor them (such as etcd, Consul)

Read configuration from command parameters

Read from buffer

Call the function to set the configuration information

Why use Viper

When building modern applications, you don't have to worry about the configuration file format; you can focus on building great software.

Viper can do the following:

Load and parse configuration files in JSON, TOML, YAML, HCL, or Java properties format

You can set default values for various configuration items

You can specify configuration items on the command line to override configuration values

An alias system is provided to rename parameters without breaking existing code

You can easily tell the difference between the command line parameters or configuration files provided by the user and the default

The priority order in which Viper reads configuration information, from high to low, is as follows:

Explicitly call the Set function

Command line argument

Environment variable

Configuration file

Key/value storage system

Default value

The key of the configuration item for Viper is case-insensitive.

Set value set default value

Default values are not required and will take effect if configuration files, environment variables, remote configuration systems, command line arguments, and Set functions are not specified.

Example:

Viper.SetDefault ("ContentDir", "content") viper.SetDefault ("LayoutDir", "layouts") viper.SetDefault ("Taxonomies", map [string] string {"tag": "tags", "category": "categories"}) reads the configuration file

Viper supports JSON, TOML, YAML, HCL, and Java properties files.

Viper can search multiple paths, but currently a single Viper instance only supports a single profile.

Viper does not search any paths by default.

The following is an example of how to use Viper to search for and read configuration files.

The path is not required, but it is best to provide at least one path to find a configuration file.

Viper.SetConfigName ("config") / / set the profile name (without suffix) viper.AddConfigPath ("/ etc/appname/") / / the first search path viper.AddConfigPath ("$HOME/.appname") / / add the path viper.AddConfigPath (".") / / for example, add the current directory err: = viper.ReadInConfig () / / search path And read the configuration data if err! = nil {panic (fmt.Errorf ("Fatal error config file:% s\ n", err))} monitor the configuration file and re-read the configuration data

Viper support gives your application the ability to read configuration files at run time.

Gone are the days when you need to restart the server for the configuration to take effect, and viper-driven applications can read updated configuration files at run time without missing any beats.

You only need to call the WatchConfig function of the viper instance, or you can specify a callback function to be notified of the change.

Viper.WatchConfig () viper.OnConfigChange (func (e fsnotify.Event) {fmt.Println ("Config file changed:", e.Name)}) reads the configuration from io.Reader

Viper predefines many configuration sources, such as files, environment variables, command-line parameters, and remote K / V storage systems, but you are not constrained by them.

You can also implement your own configuration source and provide it to viper.

Viper.SetConfigType ("yaml") / / or viper.SetConfigType ("YAML") / / any approach to require this configuration into your program.var yamlExample = [] byte (`Hacker: truename: stevehobbies:- skateboarding- snowboarding- goclothing: jacket: leather trousers: denimage: 35eyes: brownbeard: true`) viper.ReadConfig (bytes.NewBuffer (yamlExample) viper.Get ("name") / / return "steve" Set calls viper.Set ("Verbose", true) viper.Set ("LogFile", LogFile) to register and use aliases

Aliases can implement multiple key references to a single value.

Viper.RegisterAlias ("loud", "Verbose") viper.Set ("verbose", true) viper.Set ("loud", true) / / these two sentences set the same value viper.GetBool ("loud") / / trueviper.GetBool ("verbose") / / true to read from the environment variable.

Viper fully supports environment variables, which can be used right out of the box.

There are four methods related to environment variables:

AutomaticEnv ()

BindEnv (string...): error

SetEnvPrefix (string)

SetEnvKeyReplacer (string...) * strings.Replacer

Note that environment variables are case-sensitive.

Viper provides a mechanism to ensure that Env variables are unique. With SetEnvPrefix, the set prefix is added when reading from the environment variable. Both BindEnv and AutomaticEnv use this prefix.

BindEnv requires one or two parameters. The first parameter is the key name, and the second parameter is the name of the environment variable. The name of the environment variable is case-sensitive. If no ENV variable name is provided, Viper automatically assumes that the key name matches the ENV variable name and that the ENV variable is all uppercase. When you explicitly provide an ENV variable name, it does not automatically add a prefix.

When using the ENV variable, note that when associated, the ENV value is read every time it is accessed. Viper does not read the ENV value when BindEnv is called.

The combination of AutomaticEnv and SetEnvPrefix will be particularly useful. When AutomaticEnv is called, any viper.Get request gets the environment variable. The name of the environment variable is the prefix set by SetEnvPrefix, plus the capitalization of the corresponding name.

SetEnvKeyReplacer allows you to use a strings.Replacer object to rewrite the configuration name to the Env name. You can use this method if you want to use the configuration name that contains-in Get (), but you want the corresponding environment variable name to contain the _ delimiter. An example of using it can be found in the viper_test.go file in the project.

Example:

SetEnvPrefix ("spf") / / will be automatically converted to uppercase BindEnv ("id") os.Setenv ("SPF_ID", "13") / / usually through the system environment variable to set id: = Get ("id") / / 13 bind command line parameter

Viper supports binding pflags parameters.

Like BindEnv, when a bound method is called, the value is not obtained, but is obtained when it is accessed. This means that binding should be done as soon as possible, even in the init () function.

You can bind a single flag using the BindPFlag () method.

Example:

ServerCmd.Flags () .Int ("port", 1138, "Port to run Application server on") viper.BindPFlag ("port", serverCmd.Flags () .Lookup ("port")

You can also bind an existing pflag collection (pflag.FlagSet):

Pflag.Int ("flagname", 1234, "help message for flagname") pflag.Parse () viper.BindPFlags (pflag.CommandLine) I: = viper.GetInt ("flagname") / / get the value from pflag through viper

Using pflag does not affect other libraries from using flag in the standard library. Through import, pflag can take over parameters defined through the flag of the standard library. This is done by calling the AddGoFlagSet () method in the pflag package.

Example:

Package mainimport ("flag"github.com/spf13/pflag") 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 interface

If you do not want to use pflag,Viper provides two interfaces to bind other flag systems.

Use the FlagValue interface to represent a single flag. The following is a simple example that implements this interface:

Type myFlag struct {} func (f myFlag) HasChanged () bool {return false} func (f myFlag) Name () string {return "my-flag-name"} func (f myFlag) ValueString () string {return "my-flag-value"} func (f myFlag) ValueType () string {return "string"}

Once you have implemented the interface, you can bind it:

Viper.BindFlagValue ("my-flag-name", myFlag {})

Use the FlagValueSet interface to represent a set of flag. The following is a simple example that implements this interface:

Type myFlagSet struct {flags [] myFlag} func (f myFlagSet) VisitAll (fn func (FlagValue)) {for _, flag: = range flags {fn (flag)}}

Once you have implemented the interface, you can bind it:

FSet: = myFlagSet {flags: [] myFlag {myFlag {}, myFlag {}},} viper.BindFlagValues ("my-flags", fSet) supports remote Key/Value storage

To enable this feature, you need to import the viper/remot package:

Import _ "github.com/spf13/viper/remote"

Viper can read a configuration string (in JSON, TOML, YAML, or HCL format) from a path to a remote Key/Value storage system such as etcd, Consul.

These values take precedence over the default values, but are overridden by configuration from disk files, command line flag, and environment variables.

Viper uses crypt to read the configuration from the Kramp V storage system, which means that you can encrypt and store your configuration information and automatically decrypt it. Encryption is optional.

You can use a remote configuration in conjunction with a local configuration, or you can use it independently.

Crypt has a command-line tool that can help you store configuration information to the K V storage system. Crypt uses etcd on http://127.0.0.1:4001 by default.

$go get github.com/xordataexchange/crypt/bin/crypt$ crypt set-plaintext / config/hugo.json / Users/hugo/settings/config.json

Make sure your value is set:

$crypt get-plaintext / config/hugo.json

See the documentation for examples of how crypt sets encryption values or how to use Consul.

Example of remote Key/Value storage-unencrypted viper.AddRemoteProvider ("etcd", "http://127.0.0.1:4001","/config/hugo.json")viper.SetConfigType("json") / because you don't know the format, you need to specify Supported formats are "json", "toml", "yaml", "yml", "properties", "props", "prop" err: = viper.ReadRemoteConfig () remote Key/Value storage example-encrypted viper.AddSecureRemoteProvider ("etcd", "http://127.0.0.1:4001","/config/hugo.json","/etc/secrets/mykeyring.gpg")viper.SetConfigType("json") / because the format is not known, so you need to specify Supported formats are "json", "toml", "yaml", "yml", "properties", "props", "prop" err: = viper.ReadRemoteConfig () Monitoring etcd changes-unencrypted / / you can create a new viper instance var runtime_viper = viper.New () runtime_viper.AddRemoteProvider ("etcd", "viper") "/ config/hugo.yml") runtime_viper.SetConfigType ("yaml") / / because the format is not known So you need to specify Supported formats are "json", "toml", "yaml", "yml", "properties", "props", "prop" / / read configuration err from remote: = runtime_viper.ReadRemoteConfig () / / parse configuration into runtime_conf runtime_viper.Unmarshal (& runtime_conf) / / change go func () {for {time.Sleep (time.Second * 5) / / delay after each request / / currently via a remote configuration of goroutine Only tested with etcd support err: = runtime_viper.WatchRemoteConfig () if err! = nil {log.Errorf ("unable to read remote config:% v", err) continue} / / parses the new configuration into a structure variable You can also use channel to implement a signal notification runtime_viper.Unmarshal (& runtime_conf)}} () to get the value

In Viper, there are ways to get a value based on the type of value. The following methods exist:

Get (key string): interface {}

GetBool (key string): bool

GetFloat64 (key string): float64

GetInt (key string): int

GetString (key string): string

GetStringMap (key string): map [string] interface {}

GetStringMapString (key string): map [string] string

GetStringSlice (key string): [] string

GetTime (key string): time.Time

GetDuration (key string): time.Duration

IsSet (key string): bool

If the Get function does not find a value, it returns a zero value of the corresponding type. You can use the IsSet () method to detect the existence of a key.

Example:

Viper.GetString ("logfile") / / Setting & Getting is not case-sensitive if viper.GetBool ("verbose") {fmt.Println ("verbose enabled")} access nested keys

The access method also accepts nested keys. For example, if the following JSON file is loaded:

{"host": {"address": "localhost", "port": 5799}, "datastore": {"metric": {"host": "127.0.0.1", "port": 3099}, "warehouse": {"host": "198.0.0.1" "port": 2112}}

Viper can pass. Delimiters to access nested fields:

GetString ("datastore.metric.host") / / (returns "127.0.0.1")

This follows the previously established priority rules; all configurations in the path are searched until they are found.

For example, the above files, datastore.metric.host and datastore.metric.port, have been defined (and may be overwritten). If there is another default value for datastore.metric.protocol, Viper will also find it.

However, if the datastore.metricvalue is overridden (through flags, environment variables, Set methods,...), then all datastore.metric subkeys will be undefined and will be "obscured" by higher priority configuration values.

Finally, if there is a matching nested key, its value is returned. For example:

{"datastore.metric.host": "0.0.0.0", "host": {"address": "localhost", "port": 5799}, "datastore": {"metric": {"host": "127.0.0.1", "port": 3099} "warehouse": {"host": "198.0.0.1", "port": 2112}} GetString ("datastore.metric.host") / / returns "0.0.0.0" extract subtree configuration

You can extract subtrees from viper. For example, viper is configured to:

App: cache1: max-items: 100 item-size: 64 cache2: max-items: 200 item-size: 80

After execution:

Subv: = viper.Sub ("app.cache1")

Subv represents:

Max-items: 100item-size: 64

Suppose we have the following function:

Func NewCache (cfg * Viper) * Cache {...}

Its function is to create a cache based on configuration information. It is now easy to create these two caches separately:

Cfg1: = viper.Sub ("app.cache1") cache1: = NewCache (cfg1) cfg2: = viper.Sub ("app.cache2") cache2: = NewCache (cfg2) parsing configuration

You can also choose to resolve all or specific values to struct, map, and so on.

There are two ways to do this:

Unmarshal (rawVal interface {}): error

UnmarshalKey (key string, rawVal interface {}): error

For example:

Type config struct {Port int Name string PathMap string `mapstructure: "path_map" `} var C configerr: = Unmarshal (& C) if err! = nil {t.Fatalf ("unable to decode into struct,% v", err)} use a single viper or multiple viper

Viper is ready to use right out of the box. Viper can be used without any configuration or initialization. Because most applications want to be configured with a single storage center, the viper package provides this feature. It is similar to a singleton pattern.

In all of the above examples, they demonstrate how to use the singleton style of viper.

Using multiple viper instances

You can also create many different viper instances for use by your applications. Each instance has its own independent settings and configuration values. Each instance can be read from a different configuration file, Kramp V storage system, etc. All functions supported by the viper package also have corresponding viper instance methods.

Example:

X: = viper.New () y: = viper.New () x.SetDefault ("ContentDir", "content") y.SetDefault ("ContentDir", "foobar") / /.

When using multiple viper instances, users need to manage each instance themselves.

The above is all the content of the article "what is the use of the configuration information processing framework Viper in Golang". Thank you for reading! Hope to share the content to help you, more related knowledge, welcome to follow the industry information channel!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report