
Viper is a popular configuration management library for Golang. It provides a simple and efficient way to manage application configuration.
Viper supports multiple configuration file formats, including JSON, YAML, and TOML. These formats are widely used in the industry.
With Viper, you can easily read and write configuration files. This makes it a great choice for managing application settings.
Viper also provides a robust way to handle environment variables and command-line arguments.
Recommended read: Golang Programs
What is Viper?
Viper is a complete configuration solution for Go applications, including 12-Factor apps. It's designed to work within an application and can handle all types of configuration needs and formats.
Viper supports a wide range of configuration formats, including JSON, TOML, YAML, HCL, envfile, and Java properties config files. It can also read from environment variables, remote config systems like etcd or Consul, and command line flags.
Here are some of the key features of Viper:
- Setting defaults
- Reading from JSON, TOML, YAML, HCL, envfile, and Java properties config files
- Live watching and re-reading of config files (optional)
- Reading from environment variables
- Reading from remote config systems (etcd or Consul)
- Reading from command line flags
- Reading from buffer
- Setting explicit values
Env
Env is a crucial aspect of Viper, and it's great to see how it handles environment variables. Viper can read and parse configuration structure from the file, as well as read and overwrite configuration structure from environment variables.
One of the most interesting features of Viper is its ability to load environment variables into config data. This is particularly useful for developers who want to make their applications more flexible and adaptable.
Viper uses a specific order of precedence when it comes to environment variables, which is: explicit call to Set, flag, env, config, key/value store, and default. This means that environment variables will be used before config files, which is a great way to ensure that applications can be easily configured.
Here's a summary of Viper's environment variable loading capabilities:
It's worth noting that Viper configuration keys are case insensitive, although there are ongoing discussions about making this optional.
GitHub - Viper: Fangs
Viper is an open-source configuration management library for Go that allows you to consume configurations from different sources and use them within your application(s) in a standard way. This simplifies your applicationās configurations, ensuring the latest ones are used as soon as any changes are made.

Viper supports a wide range of configuration file formats, including JSON, TOML, YAML, HCL, envfile, and Java properties. It can also read from environment variables, remote config systems like etcd or Consul, and command line flags.
Viper's configuration keys are case insensitive, making it easier to work with configurations. However, there are ongoing discussions about making this optional.
Here are the different sources that Viper can read from, in order of precedence:
- Explicit call to Set
- Flag
- Env
- Config
- Key/value store
- Default
This means that if you set a value explicitly using the Set function, it will take precedence over any other source. If you provide a value through a flag, it will take precedence over environment variables, and so on.
Worth a look: Replace Value and Create a Pr Using Golang
Why Viper?
Viper is a complete configuration solution for Go applications, designed to handle all types of configuration needs and formats.
It supports reading from various config file formats like JSON, TOML, YAML, HCL, envfile, and Java properties, as well as environment variables, remote config systems, and command line flags.
Viper provides a mechanism to set default values for configuration options, making it easy to tell the difference between user-provided values and defaults.
You can use the `Set` function to explicitly set values, which takes precedence over other sources.
The precedence order for Viper configuration is: explicit call to `Set`, flag, env, config, key/value store, and default.
Here's a summary of the precedence order:
This means that if you set a value explicitly using `Set`, it will override any other values from other sources.
Discover more: Golang Set Env Variable
Config Defaults
A good configuration system will support default values, which are useful when a key hasn't been set via a config file, environment variable, remote configuration, or flag.
Default values can be set for keys, and they'll be used if a value isn't provided through one of these methods. This helps ensure that your application doesn't crash or behave unexpectedly when it encounters missing configuration.
The `ParseDefault` function, added in version 2.1.4, allows you to specify a default value for a key when binding data to a struct.
Consider reading: Declate a Map of String and Value as Map Golang
Establishing Defaults

A good configuration system will support default values, which are useful in case a key hasn't been set via config file, environment variable, remote configuration, or flag.
Default values are not required for a key, but they're still super helpful. This is especially true when working with complex systems where not all settings are always provided.
You can set default values in various ways, including using the `ParseDefault` tag on binding data to a struct. This is a handy feature that's available in version 2.1.4 and later.
The `Set` function also allows you to set a value by key string, and it defaults to `true` for `setByPath`. This means you can easily set default values using this function.
By supporting default values, a configuration system becomes more robust and easier to work with. It's a small but important detail that can make a big difference in the long run.
Here's an interesting read: How to Update a Github Using Golang
Setting Overrides
Setting Overrides is crucial for a robust configuration system. It allows you to set values for keys from various sources, such as command line flags or your application's logic.
These overrides can be used to update default values, ensuring that your application's behavior is flexible and adaptable to different scenarios. By setting overrides, you can provide a more customized experience for your users.
For instance, you can use the `Set` function to set a value by key, which has a default `setByPath` value of true. This means that the value will be set for the specified key, overriding any default value that may have been set.
You can also use the `func (*Config) LoadFlags` function to parse command line arguments and set overrides based on provided keys. This is a convenient way to allow users to customize your application's behavior through command line flags.
If this caught your attention, see: Golang Test Command
Parse Default in 2.1.4
In version 2.1.4, a new feature was added called ParseDefault, which allows you to specify a default value for a tag on binding data to a struct.
The ParseDefault tag value is used to set a default value for a field when decoding configuration data. This is especially useful when you're working with optional fields that may not be present in the configuration file.
The (*Config) Decode function, also added in version 2.1.4, decodes all config data to a destination pointer. This function is equivalent to decoding all config data to the destination pointer, making it a convenient option for working with configuration data.
Here's an interesting read: Golang Version Manager
Config Files
Viper requires minimal configuration to know where to look for config files. You can use JSON, TOML, YAML, HCL, INI, envfile, and Java Properties files.
Viper can search multiple paths, but currently, a single Viper instance only supports a single configuration file. You can handle the specific case where no config file is found by checking for its existence.
You can use a configuration file for several purposes, including declaring configuration structure, keeping defaults for each variable, documenting variables or sections, and providing a config example for app users.
Some benefits of using YAML files include hierarchical structure, clean markup, comments, and rich semantic. You can use yml.Unmarshal to parse a byte slice, but in most cases, you will work with some data provided as io.Reader implementation.
You can assign environment variables to structure fields, just like you do for JSON, YAML, and others. This will look like this:
Note that everything marked with "safe" won't overwrite any file, but just create if not existent, whilst the default behavior is to create or truncate.
Config Reading
Viper supports multiple configuration file formats, including JSON, TOML, YAML, HCL, INI, envfile, and Java Properties files.
You can configure Viper to search for config files in multiple paths, but a single Viper instance only supports a single configuration file. The application is responsible for deciding the default configuration search paths.
To read a configuration file, you can use the viper.ReadConfigs method, which accepts an io.Reader and the format of the configuration file. This allows you to pass configs from any source to Viper.
Here are the supported configuration file formats:
- JSON
- TOML
- YAML
- HCL
- INI
- envfile
- Java Properties
You can also use environment variables as configuration sources, and Viper provides a way to bind flags to configuration values.
Reading Files
Viper supports reading configuration files in various formats, including JSON, TOML, YAML, HCL, INI, envfile, and Java Properties files.
You can use Viper to search for and read a configuration file by providing at least one path where the configuration file is expected. Viper will then search for the file in that path and read its contents.
A fresh viewpoint: Golang Search
Here are some specific file formats you can use with Viper:
- JSON
- TOML
- YAML
- HCL
- INI
- envfile
- Java Properties files
Note that Viper does not default to any configuration search paths, leaving the decision to an application.
You can also handle the specific case where no config file is found by using the `ReadConfigs` method, which accepts an `io.Reader` and allows you to feed it with any data you want.
Here's an example of how to use `ReadConfigs` to read a configuration file:
```go
viper.ReadConfigs(reader)
```
This method allows you to read configuration files from any source, including files, environment variables, flags, and remote K/V stores.
Also, you can use `SetConfigType` method to tell Viper the format you are using, for example:
```go
viper.SetConfigType("json")
```
This will tell Viper that the configuration file is in JSON format.
Make sure to add all of the `configPaths` prior to calling `WatchConfig()` if you want to watch and re-read config files while running.
Here is a list of file formats supported by Viper:
- JSON
- TOML
- YAML
- HCL
- INI
- envfile
- Java Properties files
Flags
Flags are a convenient way to pass configuration data to your application from the command line. Viper supports Pflags as used in the Cobra library.
You can bind individual flags using the BindPFlag() method, which sets the value when accessed, not when the binding method is called. This means you can bind flags as early as you want, even in an init() function.
Viper also provides two Go interfaces to bind other flag systems: FlagValue and FlagValueSet. Implementing these interfaces allows you to bind your own flag systems to Viper.
To load data from CLI flags, you can use the LoadFlags function, which is a part of the Config.LoadFlags method. This function loads data from simple CLI flags parameter parsing.
Here's an example of how to define flags in the format "name:type:desc" or "name:type" or "name:desc". This allows you to specify the type and description of the flag.
For example, you can define a flag like this: "myflag:string:My flag description".
GetValue
The GetValue function is a powerful tool for retrieving values from your config data. It allows you to get a value by a given key string, and you can specify whether to find the value by its path.
You can use the GetValue function to get a value of any type, and it's especially useful when you need to retrieve a value that's not a simple string or integer.
Here are some key points to keep in mind when using the GetValue function:
- The default behavior is to find the value by its path, unless you specify otherwise.
- You can get a value of any type using the GetValue function, including integers.
To get an integer value, you can simply call the GetValue function with the key string as an argument, like this: Int get an int by key.
Config Writing
Config writing is a crucial part of working with GoLang config, and it's essential to know your options.
You can write your config to a predefined path using the WriteConfig command, but be aware that it will overwrite the existing file if it exists.
The SafeWriteConfig command is a safer alternative, as it won't overwrite the existing file, but will instead create a new one if it doesn't exist.
Here are the main config writing commands at a glance:
The "Safe" commands are a good choice if you want to avoid overwriting your config files accidentally.
Writing Files
You can write your config files using several commands in Go. The `WriteConfig` command writes the current viper configuration to the predefined path, overwriting the existing file if it exists.
There are different approaches to writing config files, and the choice depends on your specific needs. For example, you can use `WriteConfigAs` to write the config to a specific file path, overwriting the existing file if it exists.
If you want to avoid overwriting the existing file, you can use `SafeWriteConfig` or `SafeWriteConfigAs`. These commands will create a new file instead of overwriting the existing one.
Here are the different options for writing config files:
You can choose the command that best fits your needs, depending on whether you want to overwrite the existing file or create a new one.
Muststring In V2.2.0
With the release of v2.2.0, a new function called MustString was added to the config writing library.
MustString is a function that retrieves a string value by its key. It will panic if the key is empty or does not exist, making it a useful tool for ensuring data integrity.
You can use MustString to get a string value from your config file, and it will handle any errors that might occur if the key is missing or empty.
Manage Locally

Managing your configurations locally can be a breeze. You can use the LoadFiles function to load and parse config files, which will also fire the OnLoadData event.
This function is a game-changer for developers, allowing you to easily manage configurations from local sources. It's a straightforward process that gets the job done.
To take it to the next level, you can use the Watch feature to monitor loaded config files for changes. This way, you can rebind the configuration to your struct whenever the config changes.
This is particularly useful when working with dynamic configurations that need to be updated in real-time. It's a feature that's definitely worth leveraging in your projects.
Config Storage
Config storage is a crucial aspect of any Go application. You can parse command line arguments using the LoadFlags function in the Config struct.
This function takes into account the provided keys to load flags. The Set function in the Config struct allows you to set a value by key string. SetByPath is set to true by default.
You can read configurations from remote stores using Viper, which provides tools for reading configurations from Cloud Firestore, Consul, and etcd. To read configurations from Cloud Firestore, you'll need to install the Firebase package for Go and Viper using go get.
You might enjoy: Read a Custom Resource Using Cynamic Client Golang
Config Access
Accessing nested keys in Viper is straightforward, you can pass a . delimited path of keys to the accessor methods, and Viper will cascade through the remaining configuration registries until it finds the path.
You can also access array indices by using numbers in the path, for example, if you have a configuration file with an array of values, you can access the first value using the path "array[0]".
If a key matches the delimited key path, its value will be returned instead, so be careful not to shadow higher-priority configuration levels.
Viper can access a nested field by passing a . delimited path of keys, like datastore.metric.host or datastore.metric.port.
Here's a list of ways to get a value depending on the value's type:
- Get(key string) : any
- GetBool(key string) : bool
- GetFloat64(key string) : float64
- GetInt(key string) : int
- GetIntSlice(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
- AllSettings() : map[string]any
To check if a given key exists, use the IsSet() method, which returns a boolean value indicating whether the key is set.
Note that the Get function will return a zero value if it's not found, which can be useful for default values.
Config Unmarshalling
Config unmarshalling is a powerful feature in Viper that allows you to convert raw configuration data into a structured format. You can unmarshal all or a specific value to a struct, map, or other data types.
There are two main methods for unmarshalling: Unmarshal and UnmarshalKey. The Unmarshal method takes a raw value and returns an error, while the UnmarshalKey method takes a key and a raw value.
To unmarshal configuration with dot-delimited keys, you need to change the delimiter. This is useful when working with nested configuration data.
Here are the two unmarshalling methods:
- Unmarshal(rawVal any) : error
- UnmarshalKey(key string, rawVal any) : error
These methods are essential for working with configuration data in Viper.
Extracting a Sub-Tree
Extracting a sub-tree is a useful technique for developing reusable modules, allowing you to pass a subset of the configuration to a module.
This approach helps to decouple the module from the main config structure, making it easier to test and reuse.
You can do this by passing a Viper instance to the constructor that represents a subset of the configuration.
Always check the return value of Sub, as it returns nil if a key cannot be found.
This results in code that's easy to test and reuse, thanks to its decoupling from the main config structure.
If this caught your attention, see: Golang Test Main
Unmarshaling
Unmarshaling is a powerful feature in Viper that allows you to convert raw data into a struct, map, or other data structures. You can use the Unmarshal function to achieve this.
There are two methods to unmarshal data in Viper: Unmarshal and UnmarshalKey. The Unmarshal function takes a raw value and an error as arguments, while the UnmarshalKey function takes a key and a raw value as arguments, returning an error.
If your configuration keys contain dots, you'll need to change the delimiter to unmarshal them correctly. Viper supports unmarshaling into embedded structs.
Here are the two methods to unmarshal data in Viper:
- Unmarshal(rawVal any) : error
- UnmarshalKey(key string, rawVal any) : error
These methods can be used to unmarshal configuration data into a struct or map, making it easier to work with your application's settings.
Config Marshalling
Config marshalling is a crucial step in working with Go's config package. You can marshal all the settings held in viper into a string using your favorite format's marshaller with the config returned by AllSettings(). This is particularly useful when you don't need to write the settings to a file.
To marshal the config, you can use the returned config object directly with your marshaller of choice. For example, you might use the json.Marshal function to convert the config into a JSON string.
If you're working with command line flags, you can use the LoadFlags function to parse them based on the provided keys. This is a convenient way to load flag values into your config.
Worth a look: Golang Read Json File
Marshalling to String
Marshalling to string is a useful feature when you need to convert all your settings into a single string. You can use your favorite format's marshaller with the config returned by AllSettings().
If you're working with custom formats, you can use mapstructure decode hooks to parse character-separated strings into slices. This feature is already available in Viper, and you can read more about it in a specific blog post.
The Decode function can be used to decode all config data to a destination pointer. This is a feature that was added in version 2.1.4.
If you need to retrieve a string value from your config, you can use the String function, which returns a string by key or a default value if the key is not found.
Sub 2.2.4
Sub 2.2.4 is a method that allows you to get a map of config data by key. It's a crucial part of config marshalling, which is the process of converting config data into a usable format.
This method is added in version 2.2.4 of the func, and it's used to retrieve specific config data from a map. The Sub method returns a map of config data, which can be useful for accessing and manipulating config settings.
To use the Sub method, you'll need to have a map of config data available. This map can be created and populated using other methods and functions, such as the Config method. Once you have the map, you can use the Sub method to retrieve specific data by key.
Curious to learn more? Check out: Define a Map of Custom Data Type Golang
Config Case Sensitivity
Viper makes all keys case insensitive to provide the best experience when using multiple configuration sources.
This decision was made after several attempts to implement case sensitivity, which proved to be more complicated than expected.
You can vote for case sensitivity by filling out the feedback form at https://forms.gle/R6faU74qPRPAzchZ9.
If you're looking for a way to parse command line arguments, you can use the LoadFlags function, which parses based on provided keys.
The Set function can be used to set a value by key string, with setByPath defaulting to true.
To get a value from Viper, you can use one of the following functions or methods, depending on the value's type:
- Get(key string) : any
- GetBool(key string) : bool
- GetFloat64(key string) : float64
- GetInt(key string) : int
- GetIntSlice(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
- AllSettings() : map[string]any
Config Cleaning
Config cleaning is a must when working with GoLang config. Storing all configuration in a single file can lead to clutter and make it hard to manage different environments.
In the past, I've used separate config files for each environment, but this approach has its downsides. It requires storing multiple config files in the repo and updating each one after a configuration structure change.
Containers have made environment variables a common way to set up container environments. However, environment variables have an implicit nature, making it hard to debug and maintain the application.
Here's an interesting read: Playwright Testing Nextjs Config Files and Folder
A clean env approach combines several techniques to read and parse configuration structure from a file, while also overwriting it from environment variables. This approach writes a detailed variable list to the help output, making it easier to manage and understand the config.
Here's a summary of this approach:
- Reads and parses configuration structure from the file
- Reads and overwrites configuration structure from environment variables
- Writes a detailed variable list to help output
Cleaning Method
Using a single config file for all environments can be a nightmare, as I learned from experience. It's a good idea to group parameters depending on their use, but it's not very useful when you need to store several configs in the repo for each environment.
The author of the article moved to combining config with CLI arguments, which is a better approach because it allows passing some values that vary in different environments as a parameter and using the same configuration file for each system. This worked pretty well until containers came along.
Containers require a different approach, and the common way to setup a container environment is to use environment variables. However, this method has its downsides, such as its implicit nature, which makes it hard to debug and maintain.
On a similar theme: Gcloud Api Using Golang
IsEmpty

The IsEmpty function is a crucial tool in config cleaning, allowing you to quickly identify and remove empty or unnecessary configurations.
In the Config Cleaning article, we discussed how to use the IsEmpty function to check if a value is empty. This function is particularly useful when working with large config files, as it can save you a significant amount of time and effort.
Empty configurations can cause issues with your application's performance and functionality, so it's essential to remove them. As mentioned in the article, a config file with empty configurations can slow down your application's startup time and lead to errors.
The IsEmpty function can be used in a variety of scenarios, such as checking for empty strings or arrays. For example, if you have a config file with a section that contains an empty string, the IsEmpty function can help you identify and remove it.
In the article, we also discussed how to use the IsEmpty function in combination with other functions, such as the Remove function, to remove empty configurations. This can be a game-changer for config cleaning, as it allows you to automate the process and make it more efficient.
Config Usage
Config usage is straightforward, thanks to the package's simple and explicit design. The main idea is to use a structured configuration variable instead of dynamic configuration fields, which avoids unnecessary type conversions and makes the configuration easier to manage.
To use the package, you can start by loading configuration data from files or strings using functions like LoadFiles() and LoadStrings(). You can also add extra options using WithOptions(), such as ParseEnv and ParseDefault.
Some common errors to watch out for include forgetting to "defer f.Close()" the file, which can cause issues with file handling. You can also add the required format driver using AddDriver(), which is loaded by default for JSON.
Here are some key actions you can perform with the package:
Load configuration data from files or strings
Add extra options using WithOptions()
Add the required format driver using AddDriver()
Set a value by key string using the Set function
A different take: Golang Add to Map
The Set function allows you to set a value by key string, and you can also specify whether to set by path using the setByPath parameter. The LoadFlags function parses command line arguments based on provided keys, which can be useful for loading configuration data from the command line.
You might like: Os Args Golang
Config Features
The gookit/config package supports a wide range of configuration formats, including JSON, YAML, TOML, INI, HCL, ENV, and Flags.
You can load configuration data from multiple files and data sources, including system ENV and remote URLs. This makes it easy to manage complex configurations.
The package also supports data overlay and merge, automatically loading by key when loading multiple copies of data. This means you can easily combine configuration data from different sources.
Here are some of the key features of the gookit/config package:
- Support multi format: JSON, JSON5, INI, Properties, YAML, TOML, HCL, ENV, Flags
- Support multi-file and multi-data loading
- Support for loading configuration from system ENV
- Support for loading configuration data from remote URLs
- Support for setting configuration data from command line(flags)
- Support listen and fire events on config data changed
- Support data overlay and merge
- Support get sub value by key-path
- Support parse ENV name and allow with default value
- Generic API: GetInt, GetUint, GetInt64, GetFloat, GetString, GetBool, GetInts, GetIntMap, GetStrings, GetStringMap
Flag Interfaces
Flag interfaces are a crucial part of Viper's configuration management system. They allow you to bind other flag systems if you don't use Pflags.
Viper provides two Go interfaces to bind other flag systems: FlagValue and FlagValueSet. These interfaces are designed to make it easy to integrate Viper with other flag systems.
Here are some key points to consider when working with FlagValue and FlagValueSet:
Implementing these interfaces is straightforward. For example, to implement FlagValue, you can create a simple struct that meets the interface requirements, like this:
```go
type myFlag struct {
Value string
}
func (f *myFlag) Get() interface{} {
return f.Value
}
func (f *myFlag) Set(value interface{}) error {
f.Value = value.(string)
return nil
}
```
Once your flag implements the FlagValue interface, you can simply tell Viper to bind it. This allows Viper to automatically load the flag's value and make it available for use in your application.
Similarly, implementing FlagValueSet is a matter of creating a struct that meets the interface requirements and contains a collection of FlagValue instances. By implementing these interfaces, you can easily integrate Viper with other flag systems and take advantage of its powerful configuration management features.
Worth a look: Golang Copy Struct
Features
The gookit/config package supports multiple file formats, including JSON, YAML, TOML, INI, HCL, ENV, and Flags. This means you can use the format that best suits your project's needs.
You can also load configuration data from multiple files and even from remote URLs. This is incredibly useful for projects that require configuration data from multiple sources.
The package can also load configuration data from the system environment variables, making it easy to integrate with existing systems.
But that's not all - you can also set configuration data from the command line using flags. This is a huge time-saver when testing and debugging your project.
Here are some of the key features of the gookit/config package:
- Support multi format: JSON(default), JSON5, INI, Properties, YAML, TOML, HCL, ENV, Flags
- Support multi-file and multi-data loading
- Support for loading configuration from system ENV
- Support for loading configuration data from remote URLs
- Support for setting configuration data from command line(flags)
- Support listen and fire events on config data changed.
- Support data overlay and merge, automatically load by key when loading multiple copies of data
- Support for binding all or part of the configuration data to the structure
- Support get sub value by key-path, like map.keyarr.2
- Support parse ENV name and allow with default value. like envKey: ${SHELL|/bin/bash} -> envKey: /bin/zsh
- Generic API: GetInt, Uint, Int64, Float, String, Bool, Ints, IntMap, Strings, StringMap, etc.
- Complete unit test with code coverage > 95%
OSEnv Deprecated
The LoadOSEnv function has been deprecated, meaning it's no longer recommended for use. This is because it's been replaced by a more robust and flexible alternative.
If you're currently using LoadOSEnv, you'll want to switch to LoadOSEnvs() instead. This function is available in the Config object and provides more features.
You might like: Golang Reflect to Call Function in Package

LoadOSEnvs() allows you to load data from multiple OS ENVs, not just one. You can specify the format of the data using a dictionary-like structure, where each key is an ENV name and the value is a configuration key.
Here's an example of how you might use LoadOSEnvs() with a dictionary-like structure: `{ENV_NAME: config_key}`. You can even use key paths in the config key, like `"db.username"`.
Note that the LoadOSEnv() function has been marked as deprecated since version 2.1.7, so it's worth updating your code to use the new function as soon as possible.
Config API
The Config API is a powerful tool for loading and managing configuration data in your Go application. It provides a range of methods for loading data from various sources.
One of the key methods is LoadOSEnvs, which loads data from os ENV. This is useful for loading configuration data from environment variables. You can also use LoadData to load data from structs or maps.
The Config API also includes methods for loading data from command-line flags, such as LoadFlags. This method parses command-line arguments based on the provided keys.
You can also load data from files, including custom format files, using methods like LoadFiles and LoadFromDir. These methods allow you to load data from a directory and use the file name as the key.
Additionally, the Config API includes methods for loading data from remote sources, such as LoadRemote. This method loads data from a URL in a specified format.
Here's a summary of some of the key methods available in the Config API:
You can also use the Get method to retrieve a value by key, and the Set method to set a value by key. The Set method allows you to set a value by key string, and the setByPath parameter defaults to true.
The Config API also includes methods for checking if a key exists, such as Exists. This method returns true if the key exists, and false otherwise.
In addition to these methods, the Config API includes methods for working with data, such as Data and SetData. The Data method returns the current data, and the SetData method sets the data to override the Config.Data.
Worth a look: Rest Api with Golang
Config Examples
Config data can be retrieved as a map of strings to integers using the IntMap function.
To parse command line arguments, you can use the LoadFlags function of the Config struct. This function takes into account the provided keys.
You can set a value by its corresponding key string using the Set function, which has a default setting of true for setByPath.
Config data can be retrieved as a map of strings to integers using the IntMap function. This allows for easy access and manipulation of configuration values.
The LoadFlags function is used to parse command line arguments, making it a crucial part of any command-line interface.
Config Methods
Config Methods are designed to be simple and explicit, making it easy to work with structured configuration variables. You can use these methods to load configuration data from various sources, such as environment variables, command line arguments, and files.
To load configuration data from environment variables, you can use the `LoadOSEnvs()` method, which takes a `nameToKeyMap` as an argument. This method is useful when you need to load data from environment variables.
You can also use the `LoadFlags()` method to parse command line arguments based on provided keys. This method is useful when you need to load configuration data from command line arguments.
To set a value by key string, you can use the `Set()` method, which takes a key string and a value as arguments. The `setByPath` parameter is set to true by default.
Here are some useful methods that you can use to work with configuration data:
These methods provide a simple and explicit way to work with configuration data, making it easy to manage and manipulate your application's settings.
Config Reset
Config files in Golang can become corrupted or out of sync, leading to errors and inconsistencies.
One way to reset a config file is to use the `flag` package's `Reset` function, which clears all flags and their associated values.
You can also use the `flag.Parse` function to reset the flags, but this will only work if the flags were set using the `flag` package.
On a similar theme: Create a Package in Golang
Resetting a config file can be especially useful when working with distributed systems or large-scale applications, where config inconsistencies can have far-reaching consequences.
To reset a config file, you simply call the `flag.Reset` function, like this: `flag.Reset()`.
This will clear all flags and their associated values, effectively resetting the config file to its default state.
Config Set
Setting a value by key is a straightforward process in GoLang config. You can use the Set function to do this, and it's also available as a method on the Config type.
The Set function takes a key string as an argument, and it defaults to setting values by path, which is true. This means that when you set a value, it will be stored in the config under the specified path.
Loading command line arguments is another way to set values in your config. The LoadFlags function parses these arguments based on the keys you provide.
Set

Setting the value of a key is a straightforward process. You can use the Set function to achieve this.
The Set function, denoted by func Set, allows you to set a value by key. This function has a default setting of setByPath, which is true.
You can also set overrides from various sources, such as command line flags or your own application logic. These overrides can be used to modify the default settings.
The Set function is a powerful tool for managing configuration settings. It provides a flexible way to set values by key, with the option to override default settings if needed.
Set Data
Setting data is a crucial part of working with configurations. You have multiple options to set data, depending on your needs.
You can use the Set function to set a value by key string. This function has a default setting of true for setByPath.
To load data from a map or struct, you can use the LoadData function. This function accepts data in two formats: map[string]any and map[string]string.

Here are the accepted data formats for LoadData:
- map[string]any
- map[string]string
If you need to load flags from command line arguments, you can use the LoadFlags function. This function parses the arguments based on the provided keys.
The Set function can also be used to set a value by key, with setByPath defaulting to true.
Config Data
Config Data is a crucial aspect of any Go application. You can dump config data using the `config.DumpTo()` function, which exports the configuration data to a specified writer, such as a buffer or file.
The `DumpTo()` function can dump config data to a JSON file, and you can even dump pretty JSON. To customize the JSON output, you can set the `JSONMarshalIndent` variable or use a custom JSON driver.
To load data into your config, you can use the `LoadData()` function, which accepts data from a map or struct. The `dataSources` type allows for two types of data: `map[string]any` and `map[string]string`.
You might like: Convert a Map to Json Golang
You can also load flags from command line arguments using the `LoadFlags()` function, which parses arguments based on provided keys.
To set a value in your config, you can use the `Set()` function, which takes a key string and a value. The `setByPath` parameter is set to `true` by default.
Here are the supported data sources for `LoadData()`:
Config New
When working with configs in Go, you'll often need to create a new config instance. There are a few ways to do this.
You can use the `NewGeneric` function, which creates a generic config instance with custom options. By default, it adds options to parse environment variables, default values, and time.
Alternatively, you can use the `NewWith` function, which creates a config instance and allows you to call some initialization functions, including setting config options.
Here's a quick rundown of the key differences between these two functions:
Both of these functions can be useful in different situations, depending on your specific needs.
New Generic 2.2.6

The New Generic 2.2.6 update brings a game-changing feature to config new: the ability to create generic config instances with custom options.
This update adds a default set of options to the NewGeneric function, making it easier to get started with your config new setup. The options include ParseEnv, ParseDefault, and ParseTime.
With NewGeneric, you can now create a generic config instance that meets your specific needs. No more tedious configuration setup!
The default options added to NewGeneric are designed to provide a solid foundation for your config new instance. Here are the options you can expect:
- ParseEnv: parses environment variables
- ParseDefault: parses default values
- ParseTime: parses time values
These options will save you time and effort when setting up your config new instance.
New With 2.0.22
New With 2.0.22 is a feature that allows you to create a config instance.
You can call some init functions by specifying the "Options" config options.
NewWith is a function that creates a config instance, and it's available since version 2.0.22.
The init functions you can call are case insensitive, which means you can write them in any letter combination.
Config Dump
Config Dump is a feature that allows you to export your configuration data to a specified writer.
You can use the config.DumpTo() function to dump your config data to a buffer or a file, making it easy to manage and store your configuration settings.
Dumping config data to a JSON file is a common use case, and you can also use the JSONMarshalIndent variable to customize the output format.
To dump pretty JSON, you can set the default JSONMarshalIndent variable or use a custom JSON driver.
The config.DumpToFile() function is another option for dumping config data to a file, and it supports formats like JSON, YAML, and TOML.
You can specify the format when calling DumpToFile() to determine how your config data is written to the file.
Config Types
Config types in Go can be structured in various ways. You can define a config structure inside each package or library to decrease coupling, as suggested by a developer who created a small package respecting flags, files, and survey-flow, available on github.com/kataras/pkg.
A common approach is to create a main config structure with substructures for different parts of the program. This is useful for productive projects, but may not be suitable for libraries and open-source projects.
You can use a library like cleanenv, which uses regular structures with tags to read flags or values from config and environment. This allows for a clean and simple way to manage config types in Go.
Top Comments (14)
Top comments on the article about config types highlight the importance of flexibility and reusability in config management.
One commenter, Ilya, was jokingly reminded by a fellow developer to consider survey-based configuration. However, the same issue had been encountered two years ago, prompting the creation of a small package that respects flags, files, and survey flow.
Developers are actively working on simplifying configuration composition, and this article can be a helpful resource. Peter Bourgon's best practices on configuring Go applications are highly recommended for production use.

A commenter noted that using digest methods for passwords is a good practice, especially when they are exposed in clear text. One method involves digesting the input password with a hardcoded salt, making it impossible to reverse even with the encryption method known.
The difficulty of reusing Go packages due to config dependencies is a concern. One approach is to create a separate config package or structure, but this can be limiting in certain situations.
A commenter suggested attaching the configuration to the executable file, such as main.go, and then providing related configuration via public interfaces. This approach can help decrease coupling between packages.
In productive projects, a main config structure with substructures for different parts of the program can be useful. However, for libraries and open-source projects, defining config structures inside each package or library can be beneficial to decrease coupling.
Some developers prefer using flag-based configuration, but also provide env parse and config file loading. The ff library by Peter Bourgon is an example of this approach.
A commenter designed a tiny library called cleanenv, which uses regular structures with tags to read flags or values from config and environment. This approach can be useful for replacing YAML packages.
The idea of replacing the YAML package with a different one, such as pkg.go.dev/sigs.k8s.io/yaml, was also mentioned. This could potentially provide additional benefits, such as support for JSON tags.
Here's an interesting read: Go vs Golang
Bind Structure

The Bind Structure feature allows you to bind all config data to a struct. This is a powerful tool that can simplify your configuration management.
The default binding mapping tag of a structure is mapstructure, which can be changed by setting the decoder's option options.DecoderConfig.TagName. This flexibility is useful if you need to customize the binding process.
You can use the config.MapOnExists function like BindStruct, but it will only map binding if the key exists. This can be a useful option if you don't want to overwrite existing data.
To get a value by key path, you can use the Bind Structure feature. This allows you to access config data in a structured way.
Here are some key points to keep in mind when using Bind Structure:
- Default binding mapping tag is mapstructure
- Can be changed using options.DecoderConfig.TagName
- Can bind all config data to a struct
- Can map binding only if key exists using config.MapOnExists
SubDataMap 2.1.8
SubDataMap is a function that gets sub config data as a map, specifically a Map from the package maputil. This is a useful feature for managing complex configuration data.
You can use SubDataMap to retrieve specific configuration settings from a larger configuration structure. This can be particularly helpful when working with large or nested configurations.
According to the documentation, SubDataMap is part of the Config type, which is used to manage configuration data.
Here's a simple example of how you might use SubDataMap to retrieve a specific configuration setting:
```go
config := &Config{}
config.LoadFromDir("/path/to/config/dir")
subDataMap := config.SubDataMap("subconfig")
```
Float
The Float type is a convenient way to retrieve a float64 value from a Config.
You can use the Float method to get a float64 by key, as seen in the example: "func (*Config) Float¶ Float get a float64 by key". This method is a simple way to access a float value from your Config.
Just like how you might use a calculator to get a precise calculation, the Float method provides a precise float64 value for your key.
Strings
Strings can be marshalled from viper settings into a string using your favorite format's marshaller with the config returned by AllSettings().

You can use this method when you need to store settings in a string format instead of a file.
The String function returns a string by key, but if the key is not found, it returns a default value.
This is useful when you're working with dynamic settings and need a fallback value.
The LoadStrings function loads data from a string content into the config.
This is the opposite of marshalling settings into a string, and it's useful when you need to restore settings from a string.
Config Keys
Config keys in Viper can be accessed using a . delimited path of keys. This allows you to access deeply nested keys.
You can use numbers in the path to access array indices. For example, if you have a configuration file with a key like this: "datastore.metric", you can access its sub-keys like "datastore.metric.host" and "datastore.metric.port".
However, if a key is overridden with an immediate value, all its sub-keys become undefined. This means they are "shadowed" by the higher-priority configuration level.
A fresh viewpoint: Create a Map with Keys and Initialize Value Dynamically Golang
Viper makes all keys case insensitive. This is done to provide the best experience when using multiple sources with different casing. You can vote for case sensitivity in Viper v2 if you need it.
The Set function in Viper allows you to set a value by key string, and the default is to set the value by path.
Config Existence
The LoadExists function loads and parses config files, but it will ignore any files that don't exist.
This means you can use LoadExists to load your config files without worrying about errors if a file is missing. It's a convenient feature that helps prevent unnecessary errors.
The LoadExists function is part of the Config struct, which is a common way to handle configuration in Go.
Config Sources
Viper's baked-in tools are great, but you can also use viper.ReadConfigs to feed it with any data you want, as long as it's in a format Viper can understand, like JSON or YAML.
You can use viper.ReadConfigs with any data source, such as byte content, by passing an io.Reader to the method.
To tell Viper the format you're using, you can use the viper.SetConfigType method, like setting the config type to JSON.
Environment Variables
Viper treats environment variables as case sensitive.
You can use AutomaticEnv to check for an environment variable any time a viper.Get request is made, it will apply the following rules: it will check for an environment variable with a name matching the key uppercased and prefixed with the EnvPrefix if set.
AutomaticEnv is a powerful helper especially when combined with SetEnvPrefix.
Viper provides a mechanism to try to ensure that ENV variables are unique, by using SetEnvPrefix you can tell Viper to use a prefix while reading from the environment variables.
BindEnv takes one or more parameters, the first parameter is the key name, and the rest are the name of the environment variables to bind to this key.
If more than one environment variable name is provided, they will take precedence in the specified order.
The name of the environment variable is case sensitive.
If the ENV variable name is not provided, then Viper will automatically assume that the ENV variable matches the following format: prefix + "_" + the key name in ALL CAPS.
You might like: Golang Check File Exists
You can use EnvKeyReplacer with NewWithOptions factory function, it accepts a StringReplacer interface allowing you to write custom string replacing logic.
By default empty environment variables are considered unset and will fall back to the next configuration source.
You can use the AllowEmptyEnv method to treat empty environment variables as set.
Sources
Viper's built-in tools are great, but sometimes you need to read configurations from non-predefined sources. You can use the viper.ReadConfigs method, which accepts io.Reader and can read data from any source you want.
The data you pass to viper.ReadConfigs needs to be in a format that Viper can understand, such as JSON or YAML. To tell Viper the format you're using, you can use the viper.SetConfigType method.
To read configurations from any remote store, you can use Cloud Firestore as an example. The viper.ReadConfigs method will allow you to feed it with any data you want, making it a powerful tool for reading configurations.
By using viper.ReadConfigs, you can read configurations from any source, making it a flexible and adaptable solution.
Expand your knowledge: Golang Source Code
Config Structure
You can bind all config data to a struct using the `Structure` function, which gets config data and binds it to the destination struct.
The default binding mapping tag of a structure is `mapstructure`, but you can change this by setting the decoder's option `options.DecoderConfig.TagName`.
To get value by key path, you can use the `MapOnExists` function, which is similar to `BindStruct` but maps binding only if the key exists.
Here's a comparison of `MapOnExists` and `BindStruct`:
- MapOnExists maps binding only if the key exists.
- BindStruct maps binding regardless of key existence.
You can also set a value by key string using the `Set` function, which has a `setByPath` default option that's set to `true`.
Config JSON
Config JSON is a crucial part of working with golang config. You can parse command line arguments based on provided keys using the LoadFlags function.
The LoadFlags function is a convenient way to load configuration from the command line. It's a useful tool for any project that requires flexible configuration options.
To set a value by key string, you can use the Set function. This function is very straightforward and easy to use, making it a great choice for many use cases.
The Set function has a default behavior of setting values by path, which can be overridden if needed. This flexibility makes it a valuable addition to your golang configuration toolkit.
Config Writing
Writing config files is useful for storing modifications made at runtime. There are several commands available for writing config files, each with its own purpose.
The `WriteConfig` command writes the current viper configuration to the predefined path, but it will overwrite the current config file if it exists. This can be a problem if you want to preserve your current config.
The `SafeWriteConfig` command is a safer alternative that writes the current viper configuration to the predefined path without overwriting the current config file. If the file doesn't exist, it will be created.
If you want to write the config file to a custom path, you can use the `WriteConfigAs` or `SafeWriteConfigAs` commands. These commands will overwrite the file if it exists, but they give you more flexibility.
Here's a summary of the config writing commands:
The "safe" commands (`SafeWriteConfig` and `SafeWriteConfigAs`) are a good choice if you want to avoid overwriting your config file. They will create a new file if one doesn't exist, but they won't overwrite an existing file.
Curious to learn more? Check out: T Golang
[Aliases]
Aliases are a convenient way to simplify the process of loading flags and setting values in your GoLang config.
The LoadFlags function parses command line arguments based on provided keys, making it easy to load flags from the command line.
You can use this function to load flags from the command line, which can be especially useful when working on a project with multiple developers.
The Set function allows you to set a value by key string, with the option to set by path defaulting to true.
Config Introduction
Manually copying configurations across different computer systems is a needless risk.
Think about how many times a colleague created a program that required a config but didn't post it anywhere. Or had something configured differently in different places?
Personally, if I can pull up a configuration and see it myself without asking another developer, that's a huge win and saves me time.
Centralizing how your applications can read all their configurations simultaneously is huge, especially when all you have to do is update the configurations once, and you're done.
This approach improves distributed processing, team collaboration, and visibility almost overnight.
It's a big win for remote stores like databases or specialized config services, which can help fetch and make configs available to your application.
Config Learning
You can parse command line arguments using the LoadFlags function, which is based on provided keys.
To set a value by key string, you can use the Set function, which has a default setting of true for setByPath.
Here's a summary of the key points:
- LoadFlags parses command line arguments based on provided keys.
- The Set function sets a value by key string with a default of true for setByPath.
Documentation
Documentation is an essential part of the config learning process. Ints get config data as an int slice/array, which is a fundamental concept to grasp.
This means you'll need to understand how to work with arrays, even if you're not a seasoned programmer. Array manipulation is a crucial skill to develop.
In order to effectively use int slices, you'll need to learn how to index and slice arrays. This involves understanding the syntax and rules for accessing specific elements within an array.
With practice, you'll become more comfortable working with arrays and int slices, and your config learning skills will improve significantly.
For your interest: Machine Learning Golang
What You'll Learn
In this Config Learning course, you'll discover how to read and access configs from remote sources. This means you can use configurations from anywhere, not just local files.
You'll learn how to feed these remote configs to Viper, a popular configuration management tool in Go. This will standardize, access, and manage all your configurations in one central location.
With Viper, you can easily watch config changes from a remote source and provide the latest configs to your application as soon as the changes are made. This ensures your application always has the most up-to-date configurations.
Remote

Remote configuration is a powerful feature in Viper that allows you to store your configuration values in a Key/Value store like etcd or Consul.
You can enable remote support by doing a blank import of the viper/remote package. This will allow Viper to read a config string from a path in the Key/Value store.
These values take precedence over default values, but are overridden by configuration values retrieved from disk, flags, or environment variables. You can store your configuration values encrypted and have them automatically decrypted if you have the correct gpg keyring.
Viper supports multiple hosts, and you can use a list of endpoints separated by semicolons to specify them. For example, you can use http://127.0.0.1:4001;http://127.0.0.1:4002.
You can use the crypt command-line helper to put configurations in your K/V store. It defaults to etcd on http://127.0.0.1:4001.
To load config data from a remote URL, you can use the LoadRemote function. This function allows you to load config data from a remote location.
Consider reading: Simple Http Server Golang Github
Viper provides a flexible way to read configurations from remote stores, including Cloud Firestore, Consul, and etcd. You can use the LoadRemote function to load config data from a remote URL.
To set a value by key string, you can use the Set function. This function takes a key string and a value, and sets the value in the config. The setByPath default is true.
Config Non-Predefined
You're not limited to Viper's predefined configuration sources like files, environment variables, flags, and remote K/V stores. You can implement your own configuration source and feed it to viper.
Viper can read configurations from any source you want, as long as the data is in a format it understands, such as JSON or YAML.
To read configurations from a non-predefined source, you can use the viper.ReadConfigs method, which accepts an io.Reader.
The data you pass to viper.ReadConfigs can come from anywhere, but it needs to be in a format that Viper can understand.
You'll also need to tell Viper the format you're using, which you can do with the viper.SetConfigType method.
For example, if you're using JSON, you'll need to set the format to "json".
Config Dependencies
Loading command line arguments is a crucial part of config management in Go, and it's done using the LoadFlags function.
The LoadFlags function parses command line arguments based on provided keys.
You can set a value by key string using the Set function, which is a convenient way to manage your config.
The Set function takes a key string and a value, and it has a default setting of true for setByPath.
Installing dependencies and getting credentials is a necessary step when working with Firebase Cloud Firestore.
To access Cloud Firestore, you need credentials, which can be obtained from Firebase or Google Cloud Platform.
Service accounts are used to authenticate your Go application against Firebase, allowing you to query your Cloud Firestore database.
You should save the credential file in your file system and take note of the path, as you'll need it in the next step.
Curious to learn more? Check out: Golang Go
Config Firestore
You can read configurations from Cloud Firestore using a Firestore client, which allows you to fetch and watch changes in your Firestore Document.
To create a Firestore client, you need to use the option.WithCredentialsFile() method, passing the path to the credential file as the argument.
The Firestore client can then be used to read the configuration document from Cloud Firestore, which requires knowing the collection it's in and the id of the document.
This allows you to have multiple configs for different applications or users, making it ideal for syncing app configs remotely.
To access the configuration data, you need to convert the resulting map data to JSON so that you can pass it to Viper using the ReadConfig method.
The ReadConfig method accepts an io.Reader, which enables you to pass configs from any source to Viper.
This means you can read your configurations from Cloud Firestore just like any other configuration, as if it came from any other source using Viper.
Intriguing read: Google Cloud Platform Golang
Config App
The Config App is a crucial part of any Go application, allowing you to load and manage configuration data from various sources.
You can load data from os ENV using the LoadOSEnvs() method, which takes a map of string to string as an argument.
The Config App also provides methods for loading data from CLI flags, remote URLs, and custom directories.
Loading flags is as simple as calling LoadFlags() with the desired keys.
You can load data from a remote URL using the LoadRemote() method, specifying the format and URL as arguments.
The Config App supports loading data from various formats, including JSON, YAML, and more.
Here are some common methods for loading data:
The Config App also provides methods for setting and getting configuration values, such as Set() and Get().
You can set a value by key string using the Set() method, which takes the key, value, and optional setByPath argument.
The Set() method is useful for setting configuration values that are not loaded from a file or environment variable.
Here's an example of setting a value using Set():
```go
config.Set("key", "value")
```
You can also use the Get() method to retrieve a configuration value by key.
The Get() method takes the key and optional findByPath argument, and returns the value associated with the key.
Here's an example of getting a value using Get():
```go
value := config.Get("key")
```
Config Watch
Config Watch allows your application to read and react to changes in config files while running. You can achieve this by telling the viper instance to watchConfig.
To use this feature, you need to add all configPaths prior to calling WatchConfig(). This ensures that viper knows where to look for updates.
With Config Watch, your application won't miss a beat even if the config changes. Simply provide a function for viper to run each time a change occurs, and it will take care of the rest.
If the configuration changes, you can do related things like rebind the configuration to your struct. This is a useful way to keep your application in sync with the latest config settings.
Config Return
You can load config data from various sources using the provided functions.
Load data from os ENV can be done using LoadOSEnvs(nameToKeyMap map[string]string).
Loading from struts or maps is possible with LoadData(dataSource ...any) (err error).
Loading from CLI flags is handled by LoadFlags(keys []string) (err error).
There are also functions to check if a file exists, LoadExists(sourceFiles ...string) (err error), and to load files from a directory, LoadFromDir(dirPath, format string) (err error).
Here are the load functions in a list:
- LoadOSEnvs(nameToKeyMap map[string]string)
- LoadData(dataSource ...any) (err error)
- LoadFlags(keys []string) (err error)
- LoadExists(sourceFiles ...string) (err error)
- LoadFromDir(dirPath, format string) (err error)
- LoadRemote(format, url string) (err error)
- LoadSources(format string, src []byte, more ...[]byte) (err error)
- LoadStrings(format string, str string, more ...string) (err error)
- LoadFilesByFormat(format string, sourceFiles ...string) (err error)
- LoadExistsByFormat(format string, sourceFiles ...string) error
Config Getting
Getting values from your config is a crucial part of working with Go's config system. You can use the Get function with a key string to retrieve a value of any type, but be aware that it will return a zero value if the key is not found.
The Get function has several overloads, each returning a specific type of value: GetBool, GetFloat64, GetInt, GetIntSlice, GetString, GetStringMap, GetStringMapString, GetStringSlice, GetTime, and GetDuration.
These functions are useful for retrieving specific types of values from your config, but be careful not to confuse them with the IsSet method, which checks if a given key exists in the config.
Here are some of the Get functions and their return types:
The IsSet method is a useful way to check if a given key exists in the config, and can save you from having to deal with the zero value returned by the Get functions.
Featured Images: pexels.com


