(2017-02-25追記)当初は自作のisset関数を紹介していたのですが、
if .foo
やif not .foo
などで十分だということに気づいたので削除しました。
GoでHTML出力するようなWebサービスを作る場合、素で書くにせよフレームワークを採用するにせよhtml/template
のお世話になることが多いのではないでしょうか。
私も素のnet/http
+html/template
でコードを書いていますが、なぜこのテンプレート関数がないんだ!と感じることが何度かあり、自前で関数を追加して対処しました。PHP脳の私が追加した4つの関数を紹介します。
ちなみに全部Revelからのパクリです。
set
テンプレート変数に値を代入・追加できます。
これはテンプレート間で値を受け渡す場合に便利です。{{ template "foo.tpl" . }}
で呼び出されたテンプレート内でset
することで、その値を呼び出し元で参照することができます。
{{ set . "_nav" "contact" }}
また、未定義かもしれないテンプレート変数にデフォルト値を与えたいようなときにも便利です。未定義の変数にアクセスするとnil
が得られますが、変数をeq
で文字列と比較したいような場合nil
のままだとエラーになってしまいます。以下のようにデフォルト値を与えれば解決できます。
{{ if not ._nav }}
{{ set . "_nav" "" }}
{{ end }}
この関数は、parseHTML
の第三引数にmap[string]interface{}
が渡されることを想定しています。nilなどを渡すと実行時エラーになりますので注意してください。
パクリ元。
default
nil
または空文字列に対するデフォルト値を指定します。
{{ .name | default "名無しさん" }}
これはRevelのfirstof関数の引数の順序を入れ替えて2引数しか受け取れないようにしたものです。可変引数になっているのはパイプラインの前段がnil
のとき引数が渡されないことに対する対策です。
nl2br
文字列を受け取り、改行文字を<br>
に変換して表示します。
{{ .Msg | nl2br }}
パクリ元。
raw
文字列をHTMLとして表示します(自動適用されるHTMLエスケープを抑止します)
{{ .Html | raw }}
パクリ元。
ソースコード
上記4つの関数は次のようにすれば追加できます。簡単ですね。
TemplateFuncs := map[string]interface{}{
"set": func(renderArgs map[string]interface{}, key string, value interface{}) template.JS {
renderArgs[key] = value
return template.JS("")
},
"default": func(defVal interface{}, args ...interface{}) (interface{}, error) {
if len(args) >= 2 {
return nil, fmt.Errorf("wrong number of args for default: want 2 got %d", len(args)+1)
}
args = append(args, defVal)
for _, val := range args {
switch val.(type) {
case nil:
continue
case string:
if val == "" {
continue
}
return val, nil
default:
return val, nil
}
}
return nil, nil
},
// Replaces newlines with <br>
"nl2br": func(text string) template.HTML {
return template.HTML(strings.Replace(template.HTMLEscapeString(text), "\n", "<br>", -1))
},
// Skips sanitation on the parameter. Do not use with dynamic data.
"raw": func(text string) template.HTML {
return template.HTML(text)
},
}
tmpl, err := template.New("base").Funcs(TemplateFuncs).ParseFiles("...")