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
- Get the package
go get github.com/spf13/viper
- conf file
Supposed you have conf file named db.yaml
:
db:
name: somedb
host: localhost
- 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
indb.yaml
the outpt will bedb.name: mysqldb
- when we set the
name
value:somedb
in db.yaml the outpt will bedb.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"
}