Handle Go environment variables (viper)

Introduction

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

At the end

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.).

Reference material

Recommended Posts

Handle Go environment variables (viper)
Handle environment variables in Python
Shell variables, environment variables
[Python] Get environment variables
Go language environment construction
What are environment variables?
What are environment variables? (Linux)
HTTP environment variables in Flask
How to define Go variables
Environment construction, Build -Go edition-
Set environment variables with lambda-uploader
Build a go environment using Docker
Try giving AWS Lambda environment variables?
Read system environment variables with python-Part 1
Read system environment variables with python-Part 2