LoginSignup
13
9

More than 5 years have passed since last update.

html/templateに追加して便利だったテンプレート関数4選

Last updated at Posted at 2017-02-23

(2017-02-25追記)当初は自作のisset関数を紹介していたのですが、if .fooif 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("...")
13
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
9