kelseyhightower/envconfig: Golang library for managing configuration data from environment variables
ざっくり説明
環境変数を読み込んで構造体におとせるやつ。 構造体のタグに環境変数名をいれると、任意の環境変数をパースしたときに展開してくれる。 書かなくてもよしなに動く(すごい)
構造体は入れ子にできる
タグに必須有無やデフォルト値をかける。
使い方
リードミーに書いてあるので読むべし。 envconfig/README.md at master · kelseyhightower/envconfig
よしなにしてくれるが、毎回タグを書くようにしたほうが事故防止や分かりやすさからもいいと思う。
type (
// Config of the app.
Config struct {
// Service config
Environment string `envconfig:"ENVIRONMENT" required:"true"`
LogLevel string `envconfig:"LOG_LEVEL" default:"ERROR"`
Version string `envconfig:"VERSION"`
}
)
なぜ使うか
ツール類なら flag パッケージで十分だと思う。 アプリケーションとしてだと環境変数に値をいれておいて設定を変えたい場合があるのでは。 DB の接続先とか。
Laravel のときにお世話になってた dotenv もそういう感じよね。 Configuration - Laravel - The PHP Framework For Web Artisans
Go でも dotenv が出来るやつある。
joho/godotenv: A Go port of Ruby's dotenv library (Loads environment variables from .env
.)
これは構造体にシュッとならないので map 経由してよしなにやる必要ありそう。 envconfig は構造体にシュッとなって便利そうではある。
どうやって実装されているのか
これは完全に興味で羽を伸ばしてみる。
このソースだけで完結できる。意外と短い? envconfig/envconfig.go at master · kelseyhightower/envconfig
Process がエントリポイントで、すぐに gatherInfo を呼ぶ。 この中では、引数のバリデーションと、渡された構造体を reflect パッケージを使って、タグや形、キーたる名前をパースしてる。要は構造体の情報から必要なものだけ集約したもの。それが varInfo のスライスになる。 このとき、構造体のタグに split_words がついていると、ベストエフォートでキャメルケースを、スネークケースに変換してキーを設定する。
構造体を持っている場合、それがデコード出来ない形式なら再帰的にパースを試みる。 がてことは割と雑多に構造体を放り込んでもよしなに動いてくれそうではある。
このようにして、読み込んだデータを格納する構造体についての分析が終わったら、いよいよ環境変数から値を読み込む。
すでに確認されているキー名で lookupEnv(os.getenv にあたる)をして、環境変数から読み込み、なければデフォルト値を試みて required の判定をする。 読み込んだ値は文字列でしかないので、構造体の形情報に合わせて変換していく。それを processField でやっている。
このとき、対象が Decoder か Setter を実装していると、それを使って構造体のフィールドを戻そうとする。あるいは TextUnmarshar,BinaryUnmarshaler でも。
サンプルだと IP アドレスな文字列から net.Ip 構造体に落としている。 たとえばだけど暗号化した値を渡して復号化することもできし json を入れて構造体に戻すこともできるし DB 接続の情報をいれて sql.DB のクライアントを作ったり API の接続情報から http.Client を作ることもできる。 もはや設定値から作るようなものなら何でも作れる。 やりすぎるとコード読む側が苦になりそうだけど…。
話をコードに戻すと、あとはエラーの場合がある程度で、以上。
Process がエントリポイントと最初に書いたけど MustProcess というのもある。 こっちはエラーになったら panic する。
regexp.MustCompile なんかと同じ。
おわり。