はじめに
golangで環境設定ファイルを簡単にするライブラリとしてviperというものがあります。
今回はそのviperの使い方を簡単に紹介します
viper
シンプルにviperを使ってみる
今回は構造体にマッピングしてそれを引き回して使うように実装を行います
.
├── config
│   ├── config.yaml
│   └── definition.go
└── main.go
# 環境変数設定用のyamlファイル
user: 
  name: "kosuke"
本来はデータベースのユーザー名等を入れることが多いですが、今回は簡単に上記のような環境変数を設定します。
package config
import (
	"fmt"
	"github.com/spf13/viper"
)
// マッピング用の構造体
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/")  // ファイルのpathを指定
	err := viper.ReadInConfig()     // 設定ファイルを探索して読み取る
	if err != nil {            
		return nil, fmt.Errorf("設定ファイル読み込みエラー: %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
}
Load()と言う関数の中で、環境変数のファイルを探しConfigという構造体に環境変数をマッピングしていきます
package main
import (
	"fmt"
	"viper-test/config"
)
func main() {
	cfg, err := config.Load()
	if err != nil {
		panic(err)
	}
	fmt.Println(cfg.User.Name)
}
今回は構造体にデータが入っていることを確かめるためにConfigの中身を表示しているだけですが、
本来であればこの構造体を引数に撮ってDBコネクション等を行っていきます。
$ go run main.go
kosuke
また、本番環境で運用等を行うときは外部から環境変数を受けとりたいということがあると思います。
その際は、、、
package config
import (
	"fmt"
	"github.com/spf13/viper"
)
// マッピング用の構造体
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/")
    // ===========↓追記=============
    // 環境変数がすでに指定されてる場合はそちらを優先させる
	viper.AutomaticEnv()            
    // データ構造をキャメルケースに切り替える用の設定
	viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
    // ===========↑ここまで=============
	err := viper.ReadInConfig()
	if err != nil {            
		return nil, fmt.Errorf("設定ファイル読み込みエラー: %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
}
上記のような構文を使うことで環境変数が指定された時にはconfigファイルの値ではなく、
環境変数の値を参照することができます
# 環境変数を与えて `go run`
$ USER_NAME=tarou go run main.go
tarou
終わりに
今回はとてもシンプルな使い方でしたが、環境変数を構造体にマッピングして引き回していくのは余計な処理を書かなくて済むのてとても楽かなと思います。
もちろんですが、、、秘匿情報の扱い(AWSのアクセスキーなど)には気をつけて使用していきたいところです。
参考資料
- viper(https://github.com/spf13/viper )