All Articles

GoのConfigurationを統合するライブラリ書いた

Goでサービスを作るとき、設定ファイルを構造体にマップしたり、環境変数を構造体にマップしたり、コマンドライン引数を構造体にマップしたり…という処理をかなりの頻度で書くけど、いい加減統合しようってことでライブラリを書いた。

ysugimoto/twist

これは何

一般的な設定ファイル、環境変数、コマンドライン引数を統合して構造体にマッピングできる。さらにcascadingするので、

デフォルト値 -> 設定ファイル -> 環境変数 -> コマンドライン引数

のような設定値のオーバーライドも可能で、自分がよく使うパターンを全部入りでサポートした感じ。設定ファイルは、

  • toml
  • yaml
  • ini
  • json

が使えて、普通はやんないだろうけど toml読んでyaml読んで…という設定値の統合・マージもできる。もちろん設定のオーバーライド順は任意に指定可能なので好きなように設定値を生成できる。

すでにこういうのありそうな気もするけど…。

使い方

デフォルト値を設定しつつ、json -> 環境変数 の順に設定していく例はこんな感じ:

{
  "foo": "baz"
}
package main

import (
  "fmt"

  "github.com/ysugimoto/twist"
)

type Config struct {
  Foo string `default:"bar" json:"foo" env:"FOO"`
}

func main() {
  var c Config
  err := twist.Mix(&c, twist.WithJson("/path/to/example.json"), twist.WithEnv())
  if err != nil {
    panic(err)
  }
  fmt.Println(c.Foo)
}

c.Foo は初期値 bar にセットされ、JSONから baz に上書きされる(fooフィールドがない場合は上書きしない)。さらに環境変数 FOO がセットされていると、その値に上書きされる:

go run main.go
>> baz

FOO=qux go run main.go
>> qux

指定順に与えられた構造体にデータを設定するのに reflect パッケージを使ってごにょごにょいる。都度都度タグの解析をするので実行速度は遅いと思うけど、設定系は起動時に一回やるだけだろうしいいかな、と許容することにした。 タグデータをキャッシュしたりすればもう少し速くなるかもしれない。

まとめ

設定系はこれ一つでできて便利なんで使ってみてください。

現場からは以上です。