Go Cheatsheet - Read Config File

·

2 min read

Read Config File

Json

If your config file only contains a few of fields, and you don't want to install external modules, the easiest way is just using the json file.

Suppose we have a config file like below:

{
    "host": "127.0.0.1",
    "port": 8080,
    "redis": {
        "keyprefix": "golang",
        "server": "127.0.0.1:6079"
    }
}

Then we can define our structs and parse it in Go:

type rediscfg struct {
    KeyPrefix string `json:"keyprefix"`
    Server    string `json:"server"`
}

type config struct {
    Host  string   `json:"host"`
    Port  int      `json:"port"`
    Redis rediscfg `json:"redis"`
}

func main() {
    content, _ := ioutil.ReadFile("./config.json")
    var cfg config
    json.Unmarshal(content, &cfg)
}

Read Json with Viper

First we need to install viper:

$ go get github.com/spf13/viper

Then read it with Viper

import "github.com/spf13/viper"

// need to define mapstructure tag which Viper is using
type rediscfg struct {
    KeyPrefix string `json:"keyprefix" mapstructure:"keyprefix"`
    Server    string `json:"server"    mapstructure:"server"`
}

type config struct {
    Host  string   `json:"host"  mapstructure:"host"`
    Port  int      `json:"port"  mapstructure:"port"`
    Redis rediscfg `json:"redis" mapstructure:"redis"`
}

func main() {
    viper.SetConfigFile("./config.json")
    var cfg config
    if err := viper.ReadInConfig(); err != nil {
        log.Fatalln("Failed to read config file")
    }
    // use the unmarshal way
    viper.Unmarshal(&cfg)
}

An easier way is just use viper.Get function, which you don't even need to define the config struct.

// we don't need to predefine the config struct here

func main() {
    viper.SetConfigFile("./config.json")
    var cfg config
    if err := viper.ReadInConfig(); err != nil {
        log.Fatalln("Failed to read config file")
    }
    fmt.Println("Host:", viper.GetString("host"))
    fmt.Println("Redis Server:", viper.GetString("redis.server"))
}

Use YAML

With viper we can also use the yaml format. Suppose we have the yaml file like this:

host: 127.0.0.1
port: 8080

redis:
  keyprefix: golang
  server: 127.0.0.1:6379

The beauty is we only need to change the config file path:

Without defining the config struct:

func main() {
    // only need to change the config file name/path here
    viper.SetConfigFile("./config.yaml")
    var cfg config
    if err := viper.ReadInConfig(); err != nil {
        log.Fatalln("Failed to read config file")
    }
    fmt.Println("Host:", viper.GetString("host"))
    fmt.Println("Redis Server:", viper.GetString("redis.server"))
}

With defining the config struct:

import "github.com/spf13/viper"

// need to define mapstructure tag which Viper is using
type rediscfg struct {
    KeyPrefix string `json:"keyprefix" mapstructure:"keyprefix"`
    Server    string `json:"server"    mapstructure:"server"`
}

type config struct {
    Host  string   `json:"host"  mapstructure:"host"`
    Port  int      `json:"port"  mapstructure:"port"`
    Redis rediscfg `json:"redis" mapstructure:"redis"`
}

func main() {
    // only need to change the config file name/path here
    viper.SetConfigFile("./config.yaml")
    var cfg config
    if err := viper.ReadInConfig(); err != nil {
        log.Fatalln("Failed to read config file")
    }
    // use the unmarshal way
    viper.Unmarshal(&cfg)
}