There is a library called viper that simplifies the environment setting file with golang. This time I will briefly introduce how to use the viper
viper Try using viper simply This time, we will map it to a structure and implement it so that it can be used.
Source tree
.
├── config
│   ├── config.yaml
│   └── definition.go
└── main.go
config.yaml
#Yaml file for setting environment variables
user: 
  name: "kosuke"
Originally, it is common to enter the database user name etc., but this time we will easily set the above environment variables.
definition.go
package config
import (
	"fmt"
	"github.com/spf13/viper"
)
//Structure for mapping
type Config struct {
	User User   `yaml:user`
}
type User struct {
	Name string `yaml:"name"`
}
func Load() (*Config, error) {
	viper.SetConfigName("config")   //Specify the setting file name
	viper.SetConfigType("yaml")     //Specify the format of the configuration file
	viper.AddConfigPath("config/")  //Specify the file path
	err := viper.ReadInConfig()     //Search and read configuration files
	if err != nil {            
		return nil, fmt.Errorf("Configuration file read error: %s \n", err)
	}
	var cfg Config
	err = viper.Unmarshal(&cfg)
	if err != nil {
		return nil, fmt.Errorf("unmarshal error: %s \n", err)
	}
	return &cfg, nil
}
In the function called Load (), find the environment variable file and map the environment variable to the structure called Config.
main.go
package main
import (
	"fmt"
	"viper-test/config"
)
func main() {
	cfg, err := config.Load()
	if err != nil {
		panic(err)
	}
	fmt.Println(cfg.User.Name)
}
This time I'm just displaying the contents of Config to make sure the structure contains data,
Normally, we will take this structure as an argument and make a DB connection.
$ go run main.go
kosuke
Also, when operating in a production environment, you may want to receive environment variables from the outside. In that case, ...
definition.go
package config
import (
	"fmt"
	"github.com/spf13/viper"
)
//Structure for mapping
type Config struct {
	User User   `yaml:user`
}
type User struct {
	Name string `yaml:"name"`
}
func Load() (*Config, error) {
	viper.SetConfigName("config")
	viper.SetConfigType("yaml")
	viper.AddConfigPath("config/")
    // ===========↓ Addendum=============
    //If the environment variable is already specified, give priority to it.
	viper.AutomaticEnv()            
    //Settings for switching the data structure to camel case
	viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
    // ===========↑ Up to here=============
	err := viper.ReadInConfig()
	if err != nil {            
		return nil, fmt.Errorf("Configuration file read error: %s \n", err)
	}
	var cfg Config
	err = viper.Unmarshal(&cfg)
	if err != nil {
		return nil, fmt.Errorf("unmarshal error: %s \n", err)
	}
	return &cfg, nil
}
By using the above syntax, when the environment variable is specified, it is not the value of the config file, You can refer to the value of the environment variable
python
#Given environment variables`go run`
$ USER_NAME=tarou go run main.go
tarou
This time it was a very simple usage, but I think it's very easy to map environment variables to a structure and route them because you don't have to write extra processing. Of course, I would like to be careful when using confidential information (AWS access keys, etc.).
Recommended Posts