use viper to autoload env vars to struct
Introduction:
Configuration management is an important part of any software application. It helps to manage different environments such as development, staging, production, etc. Viper is one of the popular configuration management libraries written for Go. It provides a simple and efficient way to read, write and manage configuration files. In this blog post, we will focus on how to configure viper to read environment variables.
Step 1: Bind the environment variables based on the struct
The first step is traverse the structure and then bind the environment variable based on the respective struct field.
We have defined a getFlattenKeys
function which takes the prefix and the reflect value as arguments. This function is responsible for returning the flattened keys for configuration. If the value of v.Kind()
is reflect.Struct
, we traverse the structure and recursively call the getFlattenKeys
function. If the value of v.Kind()
is anything else, we append the prefix to the keys.
func getFlattenKeys(prefix string, v reflect.Value) (keys []string) {
switch v.Kind() {
case reflect.Struct:
for i := 0; i < v.NumField(); i++ {
field := v.Field(i)
name := v.Type().Field(i).Name
keys = append(keys, getFlattenKeys(prefix+name+".", field)...)
}
default:
keys = append(keys, prefix[:len(prefix)-1])
}
return keys
}
We use the getFlattenKeys
function to get the flattened keys for our configuration structure. We then bind the environment variables to the respective keys using the viper.BindEnv
function.
for _, key := range getFlattenKeys("", reflect.ValueOf(appConfig)) {
envKey := strings.ToUpper(strings.ReplaceAll(key, ".", "_"))
err := viper.BindEnv(key, envKey)
if err != nil {
logger.Fatal("config: unable to bind env: " + err.Error())
}
}
Step 2: Load the environment variables
In this step, we load the environment variables using the viper.AutomaticEnv()
function.
viper.AutomaticEnv()
This function loads all environment variables that are currently set.
Step 3: Unmarshal the environment variables into the struct
Finally, we use the viper.Unmarshal
function to unmarshal the environment variables into the struct.
if err := viper.Unmarshal(&appConfig); err != nil {
logger.Fatal("config: unable to decode into struct: " + err.Error())
}
The Unmarshal
function takes a pointer to the struct as its argument and assigns the values to the respective fields.
Conclusion:
In this blog post, we have shown how to configure viper to read environment variables. We have defined a getFlattenKeys
function that returns flattened keys for viper configuration. We have used reflection to bind the environment variables to the respective struct fields. We have then loaded the environment variables using viper.AutomaticEnv()
and unmarshaled them into the struct using viper.Unmarshal
.