'Using env variables in YML with default value

I have the following code to read config files from yml which includes ENV variables too:

confContent, err := ioutil.ReadFile("config.yml")
    if err != nil {
        panic(err)
    }
    // expand environment variables
    confContent = []byte(os.ExpandEnv(string(confContent)))
    conf := &SysConfig{}
    if err := yaml.Unmarshal(confContent, conf); err != nil {
        panic(err)
    }

config.yml

db:
  name: ${DB_NAME:qm}
  host: localhost

It is working but how can I get it to read default values if DB_NAME env is not given?

go


Solution 1:[1]

I recommend you use the awesome Viper package by spf13) to read conf files, it can solve your problem gracefully and you can use it to load many other type of conf files.

Solve your problem

  1. Get the package
    go get github.com/spf13/viper
  1. conf file

Supposed you have conf file named db.yaml:

db:
  name: somedb
  host: localhost

  1. code example

As we can see, once Viper loads the conf file, we can get values by key. A Yaml file will be parsed as a nested structure which you can unmarshal into a Golang struct, We should use viper.GetString("db.name") to get the value, you can refer to this page to get more usage info.

import (
    "fmt"

    "github.com/spf13/viper"
)

func InitConf() {
    viper.AutomaticEnv()     // read system env 
    viper.SetConfigName("db")  // conf file name to be load
    viper.AddConfigPath(".")    // conf file path

    viper.SetDefault("db.name", "mysqldb") // you can set default da name value here 

    // do read conf file and handle error
    if err := viper.ReadInConfig(); err != nil {
        if _, ok := err.(viper.ConfigFileNotFoundError); ok {
            // Config file not found; ignore error if desired
        } else {
            // Config file was found but another error was produced
        }
    }

    fmt.Printf("db.name: %s", viper.GetString("db.name"))
}

viper.AutomaticEnv() this method will read system env automatically, suppose you have an env named ENV_XXX, then you can get it by viper.GetString("ENV_XXX"). If the env name is the same as one of conf file key, viper uses the env first

  • when we do not set the name in db.yaml the output will be db.name: mysqldb
  • when we set the name value: somedb in db.yaml the output will be db.name: somedb

Hope you will find it useful! more details on usage see the Viper README file

Solution 2:[2]

I guess you had a struct for your conf like this:

Db *struct{
        Name string
        Host string
    }

so for retrieve the default variable of Dbname, you must check it like this:

if conf.Db == nil || conf.Db.Name == "" {
        conf.Db.Name = "test"
    }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Alexis Wilke
Solution 2 ttrasn