Home > front end >  Using env variables in YML with default value
Using env variables in YML with default value

Time:09-25

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?

CodePudding user response:

You can replace the mapper on ExpandEnv using Expand and take into account default values like this:

package main

import (
    "fmt"
    "os"
    "strings"
)

func main() {
    mapper := func(placeholderName string) string {
        split := strings.Split(placeholderName, ":")
        defValue := ""
        if len(split) == 2 {
            placeholderName = split[0]
            defValue = split[1]
        }

        val, ok := os.LookupEnv(placeholderName)
        if !ok {
            return defValue
        }

        return val
    }

    os.Setenv("DAY_PART", "morning")

    fmt.Println(os.Expand("Good ${DAY_PART:test}, ${NAME:Gopher}", mapper))
}

this will render

Good morning, Gopher

This is based on the example from Expand from the os package documentation.

CodePudding user response:

I recommend you to use this (Viper by spf13) awesome package to read conf file, it can solve you problem gracefully and you canuse it to load many other type of conf file

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 load conf file, we can get value by key. Yaml file will be parsed as nested structure which you can unmarshal into Golang struct, We shoule use viper.GetString("db.name") to get the value, you can refer to this page to get more usage

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 automaticly, suppose you have an env named ENV_XXX, then you can get it by viper.GetString("ENV_XXX"). If the env name as same as one of conf file key, viper will use env first

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

Hope you will find it useful! more usage you can see Viper README

CodePudding user response:

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"
    }
  •  Tags:  
  • go
  • Related