Go text/template で文字列作成
みなさん、こんにちは!
Go書いてますか?
今回は、text/template
を使って ひな形 から 文字列 を生成する方法をご紹介します。
text/template
公式が作成している 標準package なので すぐに使えます。
- template - The Go Programming Language
- https://golang.org/pkg/text/template/
似たようなpackageで html/template
というのがありますが、
これはコードインジェクションに対して安全なHTML出力を生成するものなので
そういった目的がないときは、 text/template
を使用しましょう。
- template - The Go Programming Language
- https://golang.org/pkg/html/template/
ちなみにどちらも使い方は、同じです。
使ってみる
文字列のひな形 と データ を入れ込むことによって、目的の文字列を作成します。
package main
import (
"log"
"os"
"text/template"
)
func main() {
// ひな形
tmpl := "Hello {{.}}!\n"
// template.New(<テンプレート名>).Parse(<文字列>)
t, err := template.New("sample").Parse(tmpl)
if err != nil {
log.Fatal(err)
}
// Execute(io.Writer(出力先), <データ>)
if err = t.Execute(os.Stdout, "World"); err != nil {
log.Fatal(err)
}
}
Hello World!
上記ソースのコメントのように、それぞれ指定してデータを入れるだけでできます。
構造体を使用するとき
先ほどは 1つの値のみ を データ として入れていましたが
雛形の中に 複数の違う値 を入れたいときがあると思います。
1つの方法として、構造体(struct) を使用する方法を紹介します。
package main
import (
"log"
"os"
"text/template"
)
// 構造体(すべて公開)
type Language struct {
Name string
URL string
}
func main() {
// 構造体に値を設定
data := Language{
Name: `Go`,
URL: `https://golang.org/`,
}
// ひな形
tmpl := "今回紹介する言語は、{{.Name}}です!\n詳しくは、{{.URL}} を見てください。\n"
// New(<テンプレート名>).Parse(<文字列>)
t, err := template.New("sample").Parse(tmpl)
if err != nil {
log.Fatal(err)
}
// Execute(io.Writer(出力先), <データ>)
if err = t.Execute(os.Stdout, data); err != nil {
log.Fatal(err)
}
}
今回紹介する言語は、{{.Name}}です!
詳しくは、{{.URL}} を見てください。
{{.メンバ名}}
- 構造体のメンバを指定すると値が挿入されます
今回紹介する言語は、Goです!
詳しくは、https://golang.org/ を見てください。
雛形ファイルとの連携
雛形ファイル と連携する場合は、テキストファイル を読みこむ必要がありますが
ParseFiles()
使用すると簡単に読み込むことができます。
package main
import (
"log"
"os"
"text/template"
)
func main() {
// mapの使用例
data := map[string]string{
"Name": "hiro",
"Language": "Go",
}
// New(<ファイル名>).ParseFiles(<ひな形ファイル>)
t, err := template.New("message.tmpl").ParseFiles("template/message.tmpl")
if err != nil {
log.Fatal(err)
}
// Execute(io.Writer(出力先), <データ>)
if err = t.Execute(os.Stdout, data); err != nil {
log.Fatal(err)
}
}
入力データをmapで扱う場合も同じように指定すれば出力されます
My name is {{.Name}}.
Programming in {{.Language}} language.
{{.キー名}}
- map[string]stringのキー名を指定すると値が挿入されます
My name is hiro.
Programming in Go language.
また1行で処理することもできます。
package main
import (
"log"
"os"
"text/template"
)
func main() {
// mapも使用できます
data := map[string]string{
`Name`: `hiro`,
`Language`: `Go`,
}
// Must(テンプレート) ・・・ テンプレートにエラーがあったらpanicする
t := template.Must(template.ParseFiles(`template/message.tmpl`))
// Execute(io.Writer(出力先), データ)
if err := t.Execute(os.Stdout, data); err != nil {
log.Fatal(err)
}
}
雛形ファイル内での制御構文
雛形ファイル内で if
を使ったり、range
で スライス・配列 を回すことができます。
package main
import (
"log"
"os"
"text/template"
)
type Member struct {
Name string
Comment string
}
func main() {
// 構造体のデータ
list := []Member{
{
Name: "Ken",
Comment: "hello! :)",
},
{
Name: "Nancy",
Comment: "",
},
}
// 1行で終わらせるとき
// Must(テンプレート) ・・・ テンプレートにエラーがあったらpanicする
t := template.Must(template.ParseFiles(`template/message.tmpl`))
// Execute(io.Writer(出力先), データ)
if err := t.Execute(os.Stdout, list); err != nil {
log.Fatal(err)
}
}
{{ range $i, $member := . -}}
名前 : {{ $member.Name }}
{{ if ne $member.Comment "" -}}
コメント: {{ $member.Comment }}
{{ else -}}
コメントはありません
{{ end }}
{{- end }}
range
- goの
range
関数とほぼ同じ使い方(range 配列番号, 要素 := 配列) - 右辺の
.
は、下記のソースで入れたlist
がそのまま入ってきます if
- 条件式を書く
-
ne
(__n__ot __e__qual : !=) -
ne A B
という風に指定する - 同じとする場合は、
eq A B
(__eq__ual : ==) end
- 制御構文の末尾を囲うように配置する
{{-
- 左側にある改行・スペースを削除
-}}
- 右側にある改行・スペースを削除
名前 : Ken
コメント: hello! :)
名前 : Nancy
コメントはありません
まだその他にもたくさん使えるものがあります。
自作関数を使用する
自作関数も追加できるので、いろいろ幅が広がりそうです。
package main
import (
"log"
"os"
"text/template"
)
func main() {
// 追加で使いたい関数を定義する
funcMap := template.FuncMap{
"getHogeString": getHogeString, // 追加する関数(※1)
"sum": func(x, y int) int { return x + y }, // 無名関数でもOK
}
// New(ファイル名).ParseFiles(雛形ファイル)
t, err := template.New("message.tmpl").Funcs(funcMap).ParseFiles("template/message.tmpl")
if err != nil {
log.Fatal(err)
}
// Execute(io.Writer(出力先), データ)
if err := t.Execute(os.Stdout, nil); err != nil {
log.Fatal(err)
}
}
// ※1: 追加する関数
func getHogeString() string {
return "Hoge!"
}
Say {{ getHogeString }}
1 + 2 = {{ sum 1 2 }}
Say Hoge!
1 + 2 = 3
まとめ
雛形を使った文字列作成をご紹介しました。
Execute
の出力先がio.Writer
なので、直接ファイルに書くこともできるので便利です。
是非使ってみてください。