Home > Back-end >  How to setup a golang app config according to the environment using yaml file
How to setup a golang app config according to the environment using yaml file

Time:01-28

Im trying to setup a config struct to use through my application.

Currently I load a yaml file and decode it in my config struct.

config.yml
  database_url: postgres://postgres:@localhost:5432/database_dev
config.go
import (
  "os"
  "gopkg.in/yaml.v2"
)

type AppConfig struct {
  DatabaseUrl      string `yaml:"database_url"`
}

func LoadConfig() *AppConfig {
  appConfig := &AppConfig{}
  file, _ := os.Open("config.yml")
  defer f.Close()
  decoder := yaml.NewDecoder(file)
  decoder.Decode(config)
  return appConfig
}

It works really fine, but now I need to setup different configuration according with the environment (test, local, production, etc.).

I thought that I could use a nested yaml file to declare the environments variables.

config.yml
dev:
  database_url: postgres://postgres:@localhost:5432/database_dev
test:
  database_url: postgres://postgres:@localhost:5432/database_test

I would like to receive the environment as a parameter in my LoadConfig function, and get the correct configuration. But I have no idea how to.

config.go

type configFile struct {
  Dev struct { AppConfig }`yaml:"dev"`
  Test struct { AppConfig }`yaml:"test"` 
}

func LoadConfig(env string) *AppConfig {
  appConfig := &AppConfig{}
  configFile := &configFile{}
  file, _ := os.Open("config.yml")
  defer f.Close()
  decoder := yaml.NewDecoder(file)
  decoder.Decode(configFile)
  
  // How to get the correct struct here ?
  // config = configFile["env"]
  // It doesn't works 
  // invalid operation: cannot index configFile (variable of type *configFile)


  return appConfig
}

Any suggestion is welcome.

CodePudding user response:

If the list of environments is arbitrary, then you don't want a struct for the top level; you want a map[string]AppConfig. That would look something like this:

package main

import (
  "fmt"
  "os"

  "gopkg.in/yaml.v2"
)

type (
  AppConfig struct {
    DatabaseUrl string `yaml:"database_url"`
  }

  ConfigFile map[string]*AppConfig
)

func LoadConfig(env string) (*AppConfig, error) {
  configFile := ConfigFile{}
  file, _ := os.Open("config.yml")
  defer file.Close()
  decoder := yaml.NewDecoder(file)

  // Always check for errors!
  if err := decoder.Decode(&configFile); err != nil {
    return nil, err
  }

  appConfig, ok := configFile[env]
  if !ok {
    return nil, fmt.Errorf("no such environment: %s", env)
  }

  return appConfig, nil
}

func main() {
  appConfig, err := LoadConfig(os.Args[1])
  if err != nil {
    panic(err)
  }
  fmt.Printf("config: % v\n", appConfig)
}

Assuming we have the config.yml from your question, we can run the above example with different environments and see the desired output:

$ ./example test
config: &{DatabaseUrl:postgres://postgres:@localhost:5432/database_test}
$ ./example dev
config: &{DatabaseUrl:postgres://postgres:@localhost:5432/database_dev}

CodePudding user response:

I think furthermore setting up a config file ,you should create a YML file and put this the server port... Unfortunately I am inexperienced Therefore, I may not have given the correct answer.

  • Related