サイト案内

運営してるひと: @sters9

妻と娘と猫と神奈川県に住んでいます。最近は Go, Ruby, Rails, Kubernetes, GCP, Datadog あたりをしていますがもっといろいろやりたい!

サイト案内

開発環境の紹介

プライバシーポリシー

tools.gomiba.co

サイト内検索

アーカイブ

2024/04 (7) 2024/03 (4) 2024/01 (3)

2023/12 (1) 2023/11 (3) 2023/10 (1) 2023/09 (1) 2023/08 (2) 2023/05 (4) 2023/04 (4) 2023/03 (4) 2023/02 (2) 2023/01 (1)

2022/12 (1) 2022/11 (4) 2022/10 (3) 2022/09 (2) 2022/08 (4) 2022/07 (5) 2022/06 (4) 2022/05 (9) 2022/04 (8) 2022/03 (10) 2022/02 (21) 2022/01 (8)

2021/12 (11) 2021/11 (1) 2021/10 (4) 2021/09 (2) 2021/08 (1) 2021/07 (2) 2021/06 (5) 2021/05 (10) 2021/04 (1) 2021/03 (8) 2021/02 (12) 2021/01 (8)

2020/05 (2) 2020/04 (2) 2020/02 (2) 2020/01 (1)

2019/12 (3) 2019/11 (2) 2019/10 (5) 2019/09 (3) 2019/07 (6) 2019/06 (4) 2019/04 (3) 2019/01 (2)

2018/12 (6) 2018/10 (4) 2018/09 (6) 2018/08 (7) 2018/07 (16) 2018/06 (7) 2018/05 (7) 2018/04 (5) 2018/03 (3) 2018/02 (10) 2018/01 (6)

2017/12 (8) 2017/11 (6) 2017/10 (10) 2017/09 (12) 2017/08 (12) 2017/07 (3) 2017/06 (1) 2017/01 (4)

2016/12 (5) 2016/10 (3) 2016/09 (1) 2016/07 (2) 2016/06 (1) 2016/04 (1) 2016/02 (1) 2016/01 (2)

2015/12 (1) 2015/10 (1) 2015/09 (3) 2015/06 (1) 2015/01 (1)

2014/08 (2) 2014/07 (3) 2014/05 (1) 2014/01 (7)

2013/12 (2) 2013/11 (4) 2013/10 (1) 2013/09 (1) 2013/08 (3) 2013/07 (4) 2013/06 (5) 2013/05 (2) 2013/04 (7) 2013/03 (1)

envconfig の話

この記事は公開されてから1年以上経過しており、最新の内容に追従できていない可能性があります。

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 なんかと同じ。

おわり。