Go言語:templateパッケージでHTML等テキストファイルを読み込む(応用編2)
templateパッケージでHTML等の任意のテキストファイルを読み込み、出力する方法を説明する。 応用編その2ではテンプレート内に埋め込む「アクション」で利用できる様々な機能について解説する。 なお、APIバージョンGo1で説明する。 バージョン3ではパッケージ名、関数名が異なるので注意。
概要
templateパッケージでは、任意のテキストを読み込み、テキストに埋め込まれたタグに対してデータの評価や制御(アクションという)をおこなって出力する。 templateパッケージ応用編1では、アクションの基本的な機能について説明したが、今回は以下のようなさらに高度な機能について説明する。
{{if}}
アクションにnot、and、or評価をおこなう。- 配列、Slice、Mapのサイズや任意のインデックスの値を取得する。
- 出力結果のフォーマットをおこなう。
- 任意の演算をおこなった結果を出力する。
例
not演算によりbool値を評価する
package main
import (
"fmt"
"os"
"text/template"
)
const templateString string = `
{{if not .}}TRUE {{/* not演算をおこなう */}}
{{else}}FALSE
{{end}}
`
func main() {
var t = template.Must(template.New("text").Parse(templateString))
if err := t.Execute(os.Stdout, true); err != nil { // trueを渡す
fmt.Println(err.Error())
}
}
実行結果
FALSE
and, or演算によりbool値を評価する
package main
import (
"fmt"
"os"
"text/template"
)
const templateString string = `
{{with .}}
{{if and .Field1 .Field2}}TRUE {{/* and演算をおこなう */}}
{{else}}FALSE
{{end}}
{{if or .Field1 .Field2}}TRUE {{/* or演算をおこなう */}}
{{else}}FALSE
{{end}}
{{end}}
`
type Fields struct {
Field1 bool
Field2 bool
}
func main() {
f := Fields{true, false}
var t = template.Must(template.New("text").Parse(templateString))
if err := t.Execute(os.Stdout, f); err != nil { // 構造体Fieldsを渡す
fmt.Println(err.Error())
}
}
実行結果
FALSE
TRUE
配列のサイズや任意のインデックスの値を出力する
package main
import (
"fmt"
"os"
"text/template"
)
const templateString string = `
{{len .}} {{/* 配列のサイズを出力する */}}
{{index . 1}} {{/* 配列の[1]の値を出力する */}}
`
func main() {
array := []int{1, 2, 4, 8}
var t = template.Must(template.New("text").Parse(templateString))
if err := t.Execute(os.Stdout, array); err != nil { // 配列を渡す
fmt.Println(err.Error())
}
}
実行結果
4
2
変数に一度値を格納し、出力する
package main
import (
"fmt"
"os"
"text/template"
)
const templateString string = `
{{range $i, $v := .}}{{$i}}:{{$v}}
{{end}}
`
func main() {
array := []int{1, 2, 4, 8}
var t = template.Must(template.New("text").Parse(templateString))
if err := t.Execute(os.Stdout, array); err != nil { // 配列を渡す
fmt.Println(err.Error())
}
}
実行結果
0:1
1:2
2:4
3:8
値のフォーマットを変更して出力する
package main
import (
"fmt"
"os"
"text/template"
)
const templateString string = `
{{.Tags}}
{{html .Tags}} {{/* <や"などhtmlタグに用いる文字列をエスケープする */}}
{{.Tags | html}}
{{printf "%c" .Char}} {{/* 文字型で出力する */}}
{{.Char | printf "%c"}}
`
type Fields struct {
Tags string
Char int
}
func main() {
f := Fields{"<a href="aaa">link</a>", 65}
var t = template.Must(template.New("text").Parse(templateString))
if err := t.Execute(os.Stdout, f); err != nil { // 構造体Fieldsを渡す
fmt.Println(err.Error())
}
}
実行結果
<a href="aaa">link</a>
<a href="aaa">link</a>
<a href="aaa">link</a>
A
A
構造体に定義された関数を呼び出した結果を利用する
package main
import (
"fmt"
"os"
"text/template"
)
const templateString string = `
{{if call .F .Field}}TRUE {{/* 構造体に定義されたF関数をFieldフィールドを引数として呼び出す */}}
{{else}}FALSE
{{end}}
`
type Fields struct {
Field int
F func(n int) bool
}
func validate(n int) bool {
if n > 0 {
return true
}
return false
}
func main() {
f := Fields{-10, validate}
var t = template.Must(template.New("text").Parse(templateString))
if err := t.Execute(os.Stdout, f); err != nil { // 構造体Fieldsを渡す
fmt.Println(err.Error())
}
}
実行結果
FALSE
解説
変数
{{.}}
や{{range .}} {{.}} {{end}}
のように直接値を出力するだけでなく、一度変数に格納した値を出力することができる。
任意の値を変数に格納するには以下のように記述する。
$変数名 := 値
配列の値だけでなく、インデックスを一緒に出力したい場合などに使用する。
{{range $i, $x := .}} {{$i}}:{{$x}} {{end}}
関数
- bool値の評価に
not
,and
,or
を利用できる。
not 引数
引数
のbool値をnot演算した結果を返す。
and 引数1 引数2
引数1
、引数2
のbool値をand演算した結果を返す。
or 引数1 引数2
引数1
、引数2
のbool値をor演算した結果を返す。
- 配列、Slice、Mapのサイズ取得に
len
任意のインデックスの値の取得にindex
を利用できる。
len 引数
引数
のサイズを返す。
index 引数1 引数2
引数1
のインデックス[引数2]
の値を返す。
- «や"などhtmlタグに用いる文字列をエスケープするために
html
を利用できる。
html 引数
値 | html
どちらも出力結果は同じ。
|
により、|
の左側で評価された値が右側の関数の第2引数として用いられる。
- fmtパッケージによるフォーマット変更に
print
,printf
,println
を利用できる。
print 引数1 引数2 ...
printf 引数1 引数2 ...
println 引数1 引数2 ...
値 | print 引数1
fmtパッケージの各Print系関数を利用する。
引数1
にはフォーマット、引数2
以降には出力対象の値を指定する。
使用できるフォーマットはfmtパッケージの各Print系関数と同じ。
例として以下のように使用する。
[text light="true” highlight="1”]{{printf “%c, %d” .Var1 .Var2}}[/text]
- 構造体や変数に定義された関数を呼び出すために
call
を利用できる。 templateではアクションタグ内で四則演算等、何らかのロジックを実行した結果を出力することができない。 代わりに、templateに渡す変数や構造体に定義した関数を呼び出しその結果を用いることができる。 以下のようにアクションタグを指定する。
call 関数名 (引数1) ...
関数名
で指定した関数を引数1
に続く引数で呼び出す。
引数がない場合は引数1
以降の部分は省略する。
変数や構造体には以下のように関数を定義する。
type FuncStruct struct {
F func(n int) string
}
func doSomething(n int) string {
// do something
}
func main() {
s := FuncStruct{doSomething}
...
}
この例で関数doSomething
を呼び出した結果を出力するには以下のようにアクションタグを指定する。
{{call .F 100}}