- 辻大志郎
- 約 2,100 文字
- 600 View
目次
はじめに
TIGの辻です。Go1.23連載の5本目です。
この記事では、マイナーアップデートから text/template パッケージを取り上げて紹介します。
text/template のアップデート内容
- テンプレートが新しいアクション “else with” をサポートするようになりました(#57646)
テンプレートが新しいアクション “else with” をサポートするようになりました(#57646)
text/template はテンプレートを用意し、データをテンプレートの値として当てはめて、テキスト出力できる便利なパッケージです。
FutureのいくつかのOSSでも、この text/template パッケージを利用しています。たとえば future-architect/vuls があります。
text/template パッケージで利用できる以下のようなテンプレートを用意し、このテンプレートにデータを当てはめて、結果の文字列を取得できます。
const mdTemplate = ` |
さて、テンプレート内でデータを評価するために利用できるアクション(≒構文)がいくつかあります。if や range with break などといったものです。今回のアップデートでは with に関するアクション else with が追加になりました。
withアクションとは
そもそも with のアクションを利用したことがない方も多いと思いますので、本記事で簡単に触れておきます。ちなみに私も今回の記事を書くまではテンプレートで with というアクションがあることを知りませんでした。
ドキュメントには以下のように記載があります。pipeline が空であれば、出力は生成されません。空でない場合はドットに pipeline の結果がセットされて、T1 が実行されます。
{{with pipeline}} T1 {{end}} |
テンプレートで条件分岐したい場合 if を利用すれば十分である場合が多そうですが with が有用である例として、人物名に対応するフルーツ名をテンプレート内で取得するような、次のテンプレートを考えてみます。
package main |
テンプレート内で関数を評価をして、その結果を . で参照できるため、テンプレート内のコードがシンプルになります。もちろん with ではなく if を利用しても以下のように書けますが、若干テンプレートのコードが冗長になります。
const sampleTemplate = ` |
Go 1.22までのwith
さて Go 1.22 までは with を利用したアクションは以下の2種類でした。
{{with pipeline}} T1 {{end}}{{with pipeline}} T1 {{else}} T0 {{end}}
今回のアップデートは、上記の2つのアクションに加えて else with として分岐できるようにしたい、ということです。if を利用したアクションでは以下の3種類ありますが with の場合は2種類で else with は存在しませんでした。
{{if pipeline}} T1 {{end}}{{if pipeline}} T1 {{else}} T0 {{end}}{{if pipeline}} T1 {{else if pipeline}} T0 {{end}}
この機能追加があると何が嬉しい?
例で紹介したように、テンプレート内で複雑な条件分岐している場合に、コードがシンプルになります。
#57646 のProposalを上げている willfaught さんはGoの静的サイトジェネレータであるHugoのテーマ Paige を開発されている方です。Goのテンプレートを駆使しており、実際のテンプレートのコードとして以下があったようです。
{{ with $page.Resources.GetMatch $url }} |
現実問題として、こういうコードを書かざるを得ないが、困っている、というのは Issue としてインパクトがあります。pipeline に関数を利用しており、変数 $url を関数に渡して、結果が存在すればその結果を $result 変数に値を格納しています。こういったケースでは if ではなく with が有用と感じますが Go 1.22 の構文だけですとネストが深くなってしまい、テンプレートのコードが複雑になります。
with else が導入されると上記のテンプレートコードは以下のように書き直せます。シンプルです。#57646 に記載があるこのようなユースケースを考慮して、機能追加は問題ない、としてGo1.23でリリースとなりました。
{{ with $page.Resources.GetMatch $url }} |
ちなみに else with が利用できない場合、上記のテンプレートのコードは if を利用して次のように記述できるでしょう。
{{ if $page.Resources.GetMatch $url }} |
おわりに
text/template のアップデートについて触れてみました。
with を利用しているテンプレートで複雑な条件分岐が必要なケースでは、今回のシンタックスシュガーの導入でコードがシンプルに記述できるようになるでしょう。今回のUpdateでは text/template パッケージを利用したテンプレートが複雑である場合に特に嬉しいアップデートと感じました。
次は市川さんのos.CopyFS & path/filepathです。