Goのtext/templateで、”{{“と”}}”を出力する

Goのtext/templateで、delimiterとして使われる”{{“と”}}”が含まれる文字列を出力したい。

まずは基本的な使い方を確認。”{{“と”}}”で囲んだ箇所は評価される。

https://play.golang.org/p/o0Y5CaZpIMN

package main

import (
	"log"
	"os"
	"text/template"
)


func main() {
	t := `
{{ .Foo }}
`
	tpl, err := template.New("t").Parse(t)
	if err != nil {
		log.Fatal(err)
	}
	data := map[string]interface{}{
		"Foo": "aaa",
	}
	tpl.Execute(os.Stdout, data)
}

結果は次の通り。

aaa

さて、ここからが本題。text/templateを使って、{{ foo }} というテキストを得たい場合どうするか。

素朴にエスケープしてもうまくいかない。

https://play.golang.org/p/loznU_SgNU2

package main

import (
	"log"
	"os"
	"text/template"
)

func main() {
	t := `
\{\{ foo \}\}
`
	tpl, err := template.New("t").Parse(t)
	if err != nil {
		log.Fatal(err)
	}
	data := map[string]interface{}{
		"Foo": "aaa",
	}
	tpl.Execute(os.Stdout, data)
}

\が結果に含まれてしまうため、これでは駄目。

\{\{ foo \}\}

ではどうするかというと、次のようにdelimiterの中で文字列を評価することで実現できる。

https://play.golang.org/p/ko6-P7p86fo

package main

import (
	"log"
	"os"
	"text/template"
)

func main() {
	t := `
{{ "{{ foo }}" }}
`
	tpl, err := template.New("t").Parse(t)
	if err != nil {
		log.Fatal(err)
	}
	data := map[string]interface{}{
		"Foo": "aaa",
	}
	tpl.Execute(os.Stdout, data)
}

次のように、期待した結果が出力される。テンプレートがややこしくなり、読みにくくなるが…

{{ foo }}

delimiterを変えることでも実現できる。

https://play.golang.org/p/IPUxNVPrw5Y

package main

import (
	"log"
	"os"
	"text/template"
)

func main() {
	t := `
{{ foo }}
`
	tpl, err := template.New("t").Delims("[[", "]]").Parse(t)
	if err != nil {
		log.Fatal(err)
	}
	data := map[string]interface{}{
		"Foo": "aaa",
	}
	tpl.Execute(os.Stdout, data)
}

この場合でも、期待した結果を得られる。テンプレートはスッキリするが、delimiterが普段と違うとそれはそれで混乱する気がする。

{{ foo }}

知っているとすぐ読めるけど、知らないとどうなってるのこれ?とハマりそうだな、これ。

Leave a Reply

Your email address will not be published. Required fields are marked *