
Viper is a popular Go library for managing application configurations. It provides a simple and efficient way to load and parse configuration files.
Viper supports various configuration file formats, including JSON, YAML, and TOML. It can also load configuration from environment variables and command-line flags.
One of the key benefits of using Viper is its ability to automatically reload configurations when the underlying file changes. This feature is especially useful for development environments where configurations are frequently updated.
With Viper, you can easily manage complex configurations with nested structures and arrays.
What Is
Viper is a complete configuration solution for Go applications, designed to work within an application and handle all types of configuration needs and formats.
It supports a wide range of configuration file formats, including JSON, TOML, YAML, HCL, envfile, and Java properties config files.
Viper can also read from environment variables, remote config systems like etcd or Consul, and command line flags.
You can think of Viper as a registry for all of your application's configuration needs.
Some of the key features of Viper include setting defaults, reading from various config file formats, and live watching and re-reading of config files (optional).
Here are the different ways Viper can read configuration values:
- JSON
- TOML
- YAML
- HCL
- envfile
- Java properties config files
- Environment variables
- Remote config systems (etcd or Consul)
- Command line flags
- Buffer
Getting Started
To use Viper in your Go application, you can start by implementing it in your main.go file, just like in the example code provided.
You can use Viper with the go-common Config package to abstract and standardize how configuration is loaded, validated, and injected across services. This package simplifies and unifies your configuration loading process.
The go-common Config package provides features such as required or optional YAML file loading, fallback default injection, and context-aware config propagation.
Suggestion: Golang Go
Get
To get values from Viper, you can use various functions and methods. Each function will return a zero value if the key is not found, and to check if a given key exists, you can use the IsSet() method.
A different take: Golang Use Cases

You can get values of different types using functions like GetBool(), GetFloat64(), GetInt(), GetString(), and more. For example, GetBool() returns a boolean value, while GetFloat64() returns a 64-bit floating-point number.
Here are some of the available Get functions and their return types:
- Get(key string) : any
- GetBool(key string) : bool
- GetFloat64(key string) : float64
- GetInt(key string) : int
- GetString(key string) : string
- GetStringMap(key string) : map[string]any
- GetStringMapString(key string) : map[string]string
- GetStringSlice(key string) : []string
- GetTime(key string) : time.Time
- GetDuration(key string) : time.Duration
- IsSet(key string) : bool
This makes it easy to retrieve values from Viper and use them in your application.
Flag Interfaces
Flag interfaces are a way to bind other flag systems to Viper, and they're really useful if you don't use Pflags.
Viper provides two Go interfaces to bind other flag systems: FlagValue and FlagValueSet. These interfaces allow you to bind single flags and groups of flags, respectively.
To implement the FlagValue interface, you can create a simple example that shows how to implement it, like this: Once your flag implements this interface, you can simply tell Viper to bind it.
Similarly, to implement the FlagValueSet interface, you can create a simple example that shows how to implement it: Once your flag set implements this interface, you can simply tell Viper to bind it.
Expand your knowledge: Check Type of Interface Golang
Pflags

Pflags are a powerful tool in Viper, allowing you to bind flags to your configuration. Specifically, Viper supports Pflags as used in the Cobra library.
You can bind individual flags using the BindPFlag() method, which provides the same functionality as BindEnv. This means you can bind flags as early as you want, even in an init() function.
The pflag package can handle flags defined for the flag package by importing these flags. This is accomplished by calling a convenience function provided by the pflag package called AddGoFlagSet().
Viper also provides two Go interfaces to bind other flag systems if you don't use Pflags. The FlagValue interface represents a single flag, while the FlagValueSet interface represents a group of flags.
To bind a flag, you can simply implement the FlagValue interface and tell Viper to bind it. This interface is very simple, and an example is provided in the documentation.
The BindPFlag() method is the same as a named singleton, but drives off the given *Viper. This means it's a convenient way to bind flags to your configuration.
Consider reading: Install Golang Package

You can also bind an existing set of pflags (pflag.FlagSet) using the BindPFlags() method. This method is also the same as a named singleton, but drives off the given *Viper.
In addition to binding flags, you can also use the SetPFlags() method to inform Viper about CLI flags. This method visits all flags and only identifies them as "active" pflags if they are "changed" from the CLI.
Bind Env
In Viper, you can bind environment variables to flags using the BindEnv function. This allows you to easily access environment variables from your code.
The BindEnv function is similar to a named singleton, and it drives off the given *Viper. This means you can use it to bind environment variables to your Viper instance.
To bind environment variables to flags, you can use the BindEnv function in conjunction with the AutomaticEnv function. AutomaticEnv checks ENV variables for all, which can be useful when binding environment variables to flags.
Here's a basic example of how to use BindEnv:
Configuration
Viper's configuration system is designed to support default values, which can be useful when a key hasn't been set via a config file, environment variable, remote configuration, or flag.
You can set a default value for a key using the SetDefault method, which sets the default value for a key and is used when no value is provided by the user via a flag, config, or environment variable.
Viper also supports environment variables, allowing you to integrate them dynamically into your configuration. To do this, you can create a .env file with the desired environment variables, and then use the AutomaticEnv and SetEnvKeyReplacer methods to map nested configuration keys to environment variables.
Here is a summary of the methods available for working with environment variables:
By using these methods, you can seamlessly override specific configuration values using environment variables.
For another approach, see: Gcloud Api Using Golang
Default
Default values are a crucial aspect of configuration systems. They provide a fallback value when a key hasn't been set via a config file, environment variable, remote configuration, or flag.

A good configuration system will support default values, which are not required for a key but useful in case a key hasn't been set. Default values can be set using the `SetDefault` function.
For example, in the CLI app, a default value for the flag is set using `viper.SetDefault("Flag", "Flag Value")`. This ensures that the flag value is set to "Flag Value" if it hasn't been specified.
The `SetDefault` function is the same as a named singleton, but it drives off the given *Viper instance. This means that default values are specific to the instance of Viper being used.
You can also enable or disable the inference of a key value's type when the Get function is used based upon a key's default value. This is done using the `SetTypeByDefaultValue` function.
Here's a summary of the Get functions provided by Viper:
Note that each Get function will return a zero value if it's not found, and the IsSet() method can be used to check if a given key exists.
Registering Aliases

Aliases are a powerful tool in configuration management. They allow a single value to be referenced by multiple keys.
You can think of aliases as a shortcut to a specific value in your configuration. They make it easy to reuse values across different parts of your application.
The RegisterAlias function is used to create an alias in Viper. It's essentially a named singleton that's tied to a specific *Viper instance.
By using RegisterAlias, you can give a single value multiple names, making it easier to manage your configuration.
Configuration
Configuration is a crucial aspect of any application, and Viper makes it easy to manage. You can store your configuration in a .env file, which is a simple text file that contains key-value pairs.
Viper supports environment variables, and you can use the AutomaticEnv method to automatically check for environment variables. This method is especially useful when combined with SetEnvPrefix, which allows you to add a prefix to your environment variable names.

You can also use BindEnv to bind a key to one or more environment variables. If more than one environment variable is provided, they will take precedence in the specified order. The name of the environment variable is case sensitive.
Here are the methods you can use to work with environment variables:
- AutomaticEnv()
- BindEnv(string...)
- SetEnvPrefix(string)
- SetEnvKeyReplacer(string...)
Viper treats environment variables as case sensitive, so be mindful of that when working with them.
To integrate environment variables dynamically, you can create a .env file with the following content:
You can then run the command to load the environment variables, and Viper will automatically check for environment variables.
By combining AutomaticEnv and SetEnvKeyReplacer, you can seamlessly override specific configuration values using environment variables.
Viper provides a mechanism to try to ensure that environment variables are unique by using SetEnvPrefix. This method adds a prefix to your environment variable names, which can help prevent conflicts.
Here are some examples of how to use SetEnvPrefix:
- viper.SetEnvPrefix("env")
- viper.SetEnvPrefix("config")
Note that the name of the environment variable is case sensitive, so be sure to use the correct case when working with environment variables.
Viper also provides a way to check if a given key exists using the IsSet method. This method returns a boolean value indicating whether the key exists or not.
You can use the following methods to get values from Viper:
- 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
Type Flag Value

The FlagValue interface is a crucial part of Viper's flag system.
This interface represents a single flag that users can implement to bind different flags to Viper. It's a simple concept, but it opens up a lot of possibilities for customizing Viper's behavior.
To implement FlagValue, you can create a struct that conforms to its interface. Viper will then be able to use your flag as if it were one of its own.
Once your flag implements FlagValue, you can bind it to Viper using the BindPFlag method. This allows Viper to use your flag in its configuration.
Constants
The way configuration works is based on a hierarchy of levels, with the CLI being one of the primary sources of settings. The CLI commander package, 'cobra', is used to configure variables.
Constants are a specific type of field that describe where a given 'key' (glob variable) can be configured.
The order of evaluation for config levels is important to understand, as it determines which settings are honored.
For 'dvln' needs, I've updated the table to include other ways that variables/keys can be set, so you can ignore or trim them out if you're using this in your own library.
If keys (globals/variables) have augmented description data added, settings at that level for that variable should not be honored, only valid levels should be. This is not fully implemented except for the 'dvln:' focused levels.
RemoteConfig is an optional package that can be used for VCS Pkg/Codebase related settings.
Clear P Flag
ClearPFlag is a hack used to clear Viper's knowledge of a command line flag so that an override can override a command line setting.
It's typically used when you want to prefer the Set() override setting over the pflag setting, especially if you're using SetPflags() above.
ClearPFlag is essentially a singleton, but it drives off the given *Viper.
This means it's a mechanism to clear Viper's knowledge of a flag, making it possible for an override to take precedence over the command line setting.
ClearPFlag is a bit of a workaround, but it gets the job done if you need to clear Viper's knowledge of a flag.
This is especially useful if you're working with command line flags and want to ensure that your overrides take precedence.
A unique perspective: Golang Args
File Used
ConfigFileUsed returns the file used to populate the config registry. This function is useful for checking which file Viper is currently using to populate its config registry.
You can explicitly define the path, name, and extension of the config file using SetConfigFile. This will override any config paths that Viper would normally check.
Here are some key points to keep in mind when using SetConfigFile:
- It takes three arguments: path, name, and extension.
- Viper will use this file and not check any of the config paths.
Alternatively, you can use the SetConfigFile method on a Viper instance, which is similar to the named singleton version.
To use Viper, you need to add a config path using viper.AddConfigPath. This sets the directory where the config file is located.
Get Time
You can get time values from Viper using the GetTime function, which returns a time.Time value. This function is similar to a named singleton.
The GetTime function will return a zero value if the key is not found, just like other Get functions. To check if a given key exists, use the IsSet method, which returns a boolean value.
Here are the time-related functions available in Viper:
Note that the zero value will be returned if the value is set but fails to parse as a time.Time or time.Duration value.
ReadInConfig
ReadInConfig is a fundamental function in Viper that allows you to read configuration files. It's a crucial step in reading data from your configuration files.
You can use ReadInConfig after adding config file paths and names using viper.AddConfigPath() and viper.SetConfigName(). For example, if you have a config.json file inside a configs folder, you can read data from it using viper.AddConfigPath("./configs") and viper.SetConfigName("config").
ReadInConfig is a method that's used to read the configuration from the file you've specified. It's an optional field, but it's necessary if you want to read data from your configuration files.
A different take: How to Update a Github Using Golang
Working with Viper
Working with Viper is a breeze. You can save sensitive information in your .env or any other config file and read it from there to pass it to the CLI. This is especially useful when you don't want to type sensitive information repeatedly in the CLI.
Viper supports multiple configuration file formats, including JSON, TOML, YAML, HCL, INI, envfile, and Java Properties files. You can also search multiple paths for config files, but a single Viper instance only supports a single configuration file at a time.
To use Viper, you don't need to configure or initialize it, making it a convenient choice for many applications. Viper provides a single central repository for configuration, similar to a singleton.
Additional reading: T Golang
Repository Navigation

Repository Navigation is a breeze with Viper. Many Go projects are built using Viper.
Viper is a popular tool for navigating repository files. It's widely used in the Go community, and for good reason.
One of the benefits of using Viper is that it makes it easy to work with configuration files. This is especially useful when you're working on a project with a large number of dependencies.
Viper's repository files navigation feature is a game-changer for Go developers. It helps you quickly find and work with the files you need, saving you time and effort.
Discover more: Go vs Golang
Working with Viper
Viper is a powerful configuration management tool for Go applications. It allows you to read and write configuration files in various formats, including JSON, TOML, YAML, HCL, and more.
To use Viper, you need to initialize it by calling viper.Init() or viper.New(). This will create a new Viper instance that you can use to read and write configuration files.
For another approach, see: Golang Read Json File

You can set default values for configuration keys using viper.SetDefault(). For example, you can set a default value for a flag using viper.SetDefault("Flag", "Flag Value").
Viper supports reading configuration files from various sources, including environment variables, flags, and remote Key/Value stores.
To read a configuration file, you need to call viper.ReadInConfig() and specify the path to the configuration file. You can also specify the format of the configuration file using viper.SetConfigType().
Viper provides a range of functions for getting values from the configuration, including GetString(), GetBool(), GetFloat64(), and more. Each function returns a zero value if the key is not found.
Here's a summary of the Viper functions for getting values:
You can also use Viper to watch configuration files for changes and re-read the configuration automatically. This is done by calling viper.WatchConfig().
Viper supports remote Key/Value store support, which allows you to store configuration values in a remote Key/Value store such as etcd or Consul. This can be enabled by importing the viper/remote package.
Viper also supports aliases, which permit a single value to be referenced by multiple keys. This can be useful for simplifying configuration files or for providing alternative names for configuration keys.
You can access nested keys in Viper using a . delimited path of keys. For example, if you have a configuration file with the following structure:
You can access the nested field "datastore.metric.host" using the path "datastore.metric.host".
Viper can also access array indices by using numbers in the path. For example, if you have a configuration file with the following structure:
You can access the array element at index 0 using the path "array[0]".
Overall, Viper provides a powerful and flexible configuration management tool for Go applications. Its ability to read and write configuration files in various formats, watch configuration files for changes, and support remote Key/Value store support make it an essential tool for any Go developer.
Additional reading: Golang Copy Array
Writing

Writing with Viper is a breeze. You've got four options to choose from: WriteConfig, SafeWriteConfig, WriteConfigAs, and SafeWriteConfigAs.
WriteConfig writes the current viper configuration to the predefined path, if it exists. If no predefined path exists, it will error out.
SafeWriteConfig is similar, but it won't overwrite the current config file if it already exists. It will only create a new file if one doesn't exist.
If you want more control, you can use WriteConfigAs or SafeWriteConfigAs. These methods write the current viper configuration to a specific filepath. WriteConfigAs will overwrite the file if it exists, while SafeWriteConfigAs will create a new file if one doesn't exist.
Here's a quick summary of the options:
Working with Flags
Viper supports binding to flags, specifically Pflags as used in the Cobra library. This allows you to bind flags as early as you want, even in an init() function.
The BindPFlag() method provides this functionality for individual flags. You can also bind an existing set of pflags (pflag.FlagSet) using the AddGoFlagSet() function provided by the pflag package.
Curious to learn more? Check out: Golang Function Type

Viper provides two Go interfaces to bind other flag systems if you don't use Pflags. The FlagValue interface represents a single flag, and the FlagValueSet interface represents a group of flags.
To bind a flag to Viper, you can implement the FlagValue interface. This is a simple example on how to do it:
The FlagValueSet interface is similar, but it represents a group of flags. Once your flag set implements this interface, you can tell Viper to bind it.
You can also use the BindPFlag() method to bind a specific key to a pflag (as used by cobra). This is useful when you have a Cobra instance and want to bind its flags to Viper.
Viper can handle flags defined for the flag package by importing these flags using the AddGoFlagSet() function. This is a convenient way to use other packages that use the flag package from the standard library.
By using Viper's flag binding features, you can create a robust and flexible configuration system for your application. This allows you to easily bind flags to your configuration, making it easier to manage your application's settings.
Expand your knowledge: Create a Package in Golang
Documentation
APIVersionName is a crucial setting for Viper, as it determines the name of the key in JSON output when no API version is set. If you don't set it, your JSON output will be invalid.
The APIVersionName defaults to "apiver", which means you can use that as a fallback if you don't specify a custom value.
LookName is used to customize the output format of Viper's user-focused info, which is displayed using the String() method.
If this caught your attention, see: Convert a Map to Json Golang
Key/Value Store
Viper supports remote configuration from a Key/Value store like etcd or Consul.
To enable remote support, do a blank import of the viper/remote package. You can pass a list of endpoints separated by ;, for example http://127.0.0.1:4001;http://127.0.0.1:4002.
Viper uses crypt to retrieve configuration from the K/V store, which means you can store your configuration values encrypted and have them automatically decrypted if you have the correct gpg keyring. Encryption is optional.
Remote Key/Value Store Example
You can enable remote support in Viper by doing a blank import of the viper/remote package. This allows Viper to read a config string from a Key/Value store like etcd or Consul.

These values take precedence over default values, but are overridden by configuration values retrieved from disk, flags, or environment variables.
To use multiple hosts, pass a list of endpoints separated by semicolons, for example http://127.0.0.1:4001;http://127.0.0.1:4002.
Viper uses crypt to retrieve configuration from the K/V store, which means you can store your configuration values encrypted and have them automatically decrypted if you have the correct gpg keyring. Encryption is optional.
You can use remote configuration in conjunction with local configuration, or independently of it.
The crypt command-line helper defaults to etcd on http://127.0.0.1:4001.
To confirm that your value was set, see the crypt documentation for examples of how to set encrypted values, or how to use Consul.
To add a remote provider, use the AddRemoteProvider function, which currently supports etcd and Consul. The provider string is either "etcd" or "consul", and the endpoint is the URL with the required port number.
For example, to retrieve a config file called myapp.json from /configs/myapp.json, you should set the path to /configs and set the config name to "myapp" using the SetConfigName function.
Here's an interesting read: Golang Set Env Variable
AllKeys

The AllKeys method is essentially a singleton, but it uses the given *Viper instance to drive its functionality. This means you can access all keys in your Viper instance with just one call.
It's worth noting that the AllKeys method is not a separate entity, but rather a way to access all keys within an existing Viper instance. This approach is efficient and convenient, especially when working with large key-value stores.
Marshalling and Unmarshalling
You can use Viper to marshal all settings held in viper into a string rather than write them to a file. This can be done using your favorite format's marshaller with the config returned by AllSettings().
Viper supports unmarshaling into embedded structs, making it a powerful tool for working with configuration data. To unmarshal configuration where the keys themselves contain dot (the default key delimiter), you have to change the delimiter.
Here are the two methods to unmarshal configuration with Viper:
- Unmarshal(rawVal any) : error
- UnmarshalKey(key string, rawVal any) : error
Both methods can be used to unmarshal configuration into a struct, map, etc.
Marshalling

Marshalling is the process of converting a string into a format that can be easily read and used by your application. This can be useful when you need to store configuration settings in a file.
You can use Viper's `AllSettings()` function to get a config object that can be marshalled into a string. This config object can then be used with your favorite format's marshaller.
For example, you can use the `json` package to marshal the config into a JSON string.
GetInt64
The GetInt64 function is a useful tool for retrieving integer values from a key. It's a straightforward way to get the job done, returning the value associated with the key as an integer.
Using GetInt64 is as simple as calling the function with a key, and it will return the integer value. This can be particularly useful when working with marshalled data.
The GetInt64 function is designed to handle integer values, making it a great choice for situations where you need to retrieve an integer from a key.
Type Use Level
Type Use Level is a concept that helps determine when a user should be able to access a specific config key or variable.
It indicates the level of user that should be "at" to use a given config key, meaning they likely don't want to be setting or playing with it until they reach a given level.
UseLevels available are just integers at this point, which can be used to restrict access to certain config keys based on a user's level.
In essence, UseLevel is a way to lock down certain config keys to prevent users from accessing them prematurely.
Return
As you return to your code, you'll want to make sure you're handling the results of marshalling and unmarshalling correctly.
The InConfig function in Viper is similar to a singleton, but it uses the given *Viper instance.
To ensure data integrity, you should always check the return value of your marshalling and unmarshalling functions to see if they were successful.
The InConfig function is a singleton, driving off the given *Viper instance.
Best Practices
When working with Go and Viper, it's essential to follow best practices to ensure your application runs smoothly and securely.
Use environment variables for sensitive data instead of storing secrets in config files. This is a simple yet effective way to keep your application safe.
Setting default values is also crucial. You can use viper.SetDefault("key", value) to ensure your application has sensible defaults. This helps prevent runtime errors and makes your code more maintainable.
To keep your configuration organized, group related configurations together and use nested structs for clarity. This makes it easier to understand and work with your config files.
Origin of the Name
The origin of the name "Viper" is an interesting story. Viper is designed to be a companion to Cobra, working together to handle much of your application foundation needs.
I can imagine that having a pair of tools like Viper and Cobra would be incredibly powerful. While both can operate completely independently, together they make a formidable team.
In this case, the name "Viper" likely refers to its ability to work alongside Cobra, making them a dynamic duo.
Best Practices

When handling sensitive data, it's a good idea to avoid storing secrets in config files. Use environment variables or secret management tools instead.
Storing secrets in config files can be a major security risk. Environment variables and secret management tools provide a safer and more secure way to handle sensitive data.
To ensure your application has sensible defaults, use viper.SetDefault("key", value). This helps prevent runtime errors caused by missing or incorrect configuration values.
Having sensible defaults also makes your application more robust and easier to maintain. It's a good practice to set default values for all configuration keys.
Validating configuration after loading it is crucial to prevent runtime errors. This step ensures that your application only uses valid and expected configuration values.
Validating configuration also helps catch any issues early on, making it easier to debug and troubleshoot problems.
Here are some best practices to keep your configuration organized:
- Group related configurations together
- Use nested structs for clarity
By following these best practices, you can keep your configuration organized and easy to understand. This makes it simpler to maintain and update your application.
Clear
Clearing out previously added config file paths and names is crucial for a clean start in each run. This is especially important when switching between different test hardness levels.
The ClearConfigSettings function is designed to do just that, clearing out any previously added config file paths and names. It allows the next run to re-determine what config file to read in from scratch.
ClearConfigSettings is also available as a method of the Viper singleton, making it easily accessible. This is a convenient option for those who prefer to use the singleton pattern.
Clearing out previous config settings is a simple yet effective way to ensure a fresh start in each run. It helps prevent any potential issues caused by leftover config settings.
Take a look at this: How to Run a Golang Program
Advanced Topics
Golang Viper allows for advanced configuration management through its support for multiple configuration sources.
You can use the `viper.RegisterAlias` method to register an alias for a configuration source, which can be useful for complex applications with multiple configuration files.
This allows you to easily switch between different configuration sources without having to modify your code.
Watching and Re-reading

Watching and re-reading config files is a game-changer for developers. Gone are the days of needing to restart a server to have a config take effect.
You can use Viper to have your application live read a config file while running. Simply tell the viper instance to watchConfig.
Optionally, you can provide a function for Viper to run each time a change occurs. This can be super helpful for automating tasks or updating your application in real-time.
Make sure you add all of the configPaths prior to calling WatchConfig(). This is a crucial step to ensure that Viper can monitor your config file for changes.
Viper predefines many configuration sources, including files, environment variables, flags, and remote K/V store. However, you're not limited to these options.
You might like: Golang Application
Concurrent Read/Write Safety
You'll need to synchronize access to a viper if you want to read and write to it at the same time.
Concurrent reads and writes can cause a panic, so it's essential to handle this situation carefully.
AddSecureRemoteProvider

AddSecureRemoteProvider is a function that allows you to add a secure remote configuration source.
To use AddSecureRemoteProvider, you need to specify the type of provider, which can be either "etcd" or "consul". You also need to provide the endpoint URL, which for "etcd" requires the format "http://ip:port" and for "consul" requires just "ip:port".
The path parameter determines the location in the key-value store where the configuration file is stored. For example, to retrieve a config file called "myapp.json" from "/configs/myapp.json", you should set the path to "/configs" and then use the SetConfigName() function to specify the config name as "myapp".
Error Handling
Error Handling is crucial when working with Viper, and it's good to know that Viper returns an error when encountering an unsupported configuration.
The error type returned is called UnsupportedConfigError, and it has an Error method that provides a string describing the error.
If you're not sure what's causing the error, you can check the priority of Viper's configuration sources to see where the issue might be.
The priority is as follows: overrides, flags, env. variables, config file, key/value store, the dvln codebase and pkg settings, and finally defaults.
This means that if you're using the defaults and encountering an error, it's likely due to a misconfiguration in one of the higher-priority sources.
A fresh viewpoint: Golang Create Error
Frequently Asked Questions
Why use Viper?
Use Viper to easily manage and reload configuration from various sources, streamlining your development process and reducing application restarts
Featured Images: pexels.com


