私は作るツールの設定ファイルのフォーマットをYAMLにすることが多いです。
そして各値で環境変数を展開できるようにする機能を追加することがあります。
以下のような設定ファイルを読み込んだ際に、${COVERAGE_ACCEPTABLE} や${COVERAGE_BADGE_PATH} を環境変数から読み込んで変数展開してあげる機能を追加します。
coverage:acceptable: ${COVERAGE_ACCEPTABLE}badge:path: ${COVERAGE_BADGE_PATH}comment:enable: ${COMMENT_ENABLE}
値が文字列であればYAMLファイルをエンコードしてからos.Expandenv を呼べばいいですし、今まではそのように作っていたのですが以下のような課題がありました。
${xxxxx} はどう見ても文字列なので、数値や真偽値の変数展開を実現するためにはUnmarshalする際に一工夫が必要になります。
そこまでの実装のモチベーションが持てず、大抵「環境変数展開対象外」にしていました。
YAMLの文字列を構造体に変更した後に変数展開をする場合、os.Expandenvを各値に対してひたすら適用する必要があります*1。適用漏れもあったり。
そういったYAMLを設定ファイルに採用しているツールが手元に増えてきたので、YAMLファイルの全ての値に対してos.Expandenv(os.Expand)を適用する関数を作ってみました。
使い方は簡単で、以下のようにexpand.Expand* を呼べば []byte や string なYAMLの各値にだけos.Expandenv(os.Expand)を適用します。
c := &Config{}p :="config.yml"buf, err := os.ReadFile(p)if err !=nil {return err}if err := yaml.Unmarshal(expand.ExpandenvYAMLBytes(buf), c); err !=nil {return err}提供している関数はexpand package - github.com/k1LoW/expand - pkg.go.dev をみてください。
実装は、ありがたいことにgithub.com/goccy/go-yaml が Lexer をpublicなAPIとして公開してくれているので、それを利用させてもらっています。Lexer の活用事例としてycat があり、かなり参考にさせてもらいました*2。
せっかくYAMLのための関数を作ったので、他のフォーマットや構造体の関数も作ってみようかなとは思いました。思っただけです。
もし何かあればフィードバックもらえると嬉しいです。
引用をストックしました
引用するにはまずログインしてください
引用をストックできませんでした。再度お試しください
限定公開記事のため引用できません。