【Go実践】html/templateパッケージ ‐ GoのHTMLテンプレート機能を利用する

シェアする

これから、入力フォームやログイン機能などWEBアプリケーションの実際的な画面機能を実装していきます。
それにあたり、フォームからPOSTされたデータをプログラムで処理して画面に表示する、などの処理が必要になってきます。

先だって、今回の記事ではHTMLテンプレートの使用方法を解説したいと思います。

html/templateパッケージ

Goの標準パッケージの一つであるhtml/templateは、PHPやJavaなどの他言語にもみられるテンプレートエンジンのような機能を提供します。
html/templateパッケージが実装るテンプレートは、コードインジェクション対策が施された安全なHTMLを生成します。

外部ライブラリに頼らずセキュアで実用的なHTMLテンプレートを利用できるのは、Web開発におけるGoのメリットの一つといってもよいかもしれません。

テンプレートの記述方法

それではまず、HTMLテンプレートの記述方法をみてみましょう。
新しくtemplatesディレクトリを作成し、その中にsample.gtplというファイルを作成します。
拡張子は任意ですが、ここではgoのテンプレートファイルであることを表すgtplという拡張子にしています。

templates/sample.gtplファイルを作成したら、以下のように記述してみてください。

<!DOCTYPE html>
<html>
<body>
    <table>
      <tr>
        <td>アカウント名:</td>
        <td>{{.account}}</td>
      </tr>
      <tr>
        <td>お名前:</td>
        <td>{{.name}}</td>
      </tr>
      <tr>
        <td>パスワード:</td>
        <td>{{.passwd}}</td>
      </tr>
    </table>
</body>
</html>

前回の記事で作成したユーザ情報テーブルの項目を表示するテンプレート内容です。
7行目の{{.account}}、11行目の{{.name}}、15行目の{{.passwd}}にGoプログラムからデータを流し込みます。

データを流入するフィールドは{{ }}で囲み、.で開始するフィールド名を記述します。

テンプレート出力に使用するメソッド

続いて、テンプレートを出力するためのGoプログラム側の処理を解説します。
html/templateパッケージの3つのメソッドを利用することで、先ほどのテンプレートを表示できます。

ParseFilesメソッド ― テンプレートの解析

まず、作成済のテンプレートを読み込むために、ParseFilesを使用します。

func ParseFiles([テンプレートファイルのパス] string) (*Template, error)

ParseFilesメソッドは、指定されたファイルからテンプレート定義を解析します。
返されたテンプレートの名前は、最初のファイル名と解析されたHTML内容を持ちます。
エラーが発生した場合、解析は停止され、戻り値の*Templateにはnilが返されます。

Mustメソッド ― テンプレートの初期化

次にテンプレートを格納するオブジェクト変数の初期化メソッドとして、Mustを使用します。

func Must([テンプレート] *Template) *Template

Mustメソッドは、引数で渡されたテンプレートを返す関数への呼び出しをラップするヘルパーです。
パースしたテンプレートを引数に指定して使用します。
エラーがnil以外の場合はパニックが発生します。

ExecuteTemplateメソッド ― テンプレートの実行

最後に、流入するデータを指定してテンプレートを描画するExecuteTemplateメソッドです。

func (t *Template) ExecuteTemplate([http.ResponseWriter] io.Writer, [テンプレート名] string, [流入するデータ] interface{}) error

ExecuteTemplateは、指定された名前を持つテンプレートをデータオブジェクトに適用し、出力をhttp.ResponseWriterに書き込みます。
テンプレートの出力中にエラーが発生した場合、実行は停止しますが、部分的な結果はすでにhttp.ResponseWriterに書き込まれている可能性があります。

テンプレートを表示するプログラム

それでは、前述のメソッドを利用し、テンプレートに実値を流入して出力するサンプルを実装してみましょう。
なお、GoでHTTPサーバを実装する方法については下記のリンクをご参照ください。
【Go入門】net/httpパッケージを使ったWEBサーバの構築とHTTPリクエストハンドラの実装

package main

import (
    "fmt"
    "html/template"
    "net/http"
)

func gtplHandler(w http.ResponseWriter, r *http.Request) {

    // テンプレートをパースする
    tpl := template.Must(template.ParseFiles("templates/sample.gtpl"))

    // テンプレートに出力する値をマップにセット
    values := map[string]string{
        "account": "user-0001",
        "name":    "山田太郎",
        "passwd":  "sample-pass",
    }

    // マップを展開してテンプレートを出力する
    if err := tpl.ExecuteTemplate(w, "sample.gtpl", values); err != nil {
        fmt.Println(err)
    }
}

func main() {
    // ルートへのリクエストを"gtplHandler"関数で処理する
    http.HandleFunc("/", gtplHandler)

    // localhost:8080でサーバー処理開始
    http.ListenAndServe(":8080", nil)
}

13行目に注目してください。
このサンプルでは、テンプレートに流入するデータオブジェクトにマップを使用しています。
マップの使い方についてはこの記事をご参照ください。
【Go入門】参照型・マップ – Goの連想配列

このマップのキー名がそれぞれ、テンプレートの変数フィールド名に対応しています。
なお、マップではなく構造体を使用することも可能です。

それではこのコードを実行し、ブラウザでhttp://localhost:8080/にアクセスしてみてください。
以下のように出力されます。

main.go内でマップにセットした変数値が、テンプレートに展開された状態で描画されていることがお解りいただけると思います。

終わりに

今回は、html/templateパッケージを使用してする方法を解説しました。
テンプレートの使用は、デザインとビジネスロジックを分離できるというメンテナンス面でのメリットがあるだけでなく、コードインジェクション対策というセキュリティ措置としても必要な技術です。

次回の記事では、入力フォームからPOSTされた値を処理して、今回作成したテンプレートに出力するサンプルを作成します。

スポンサーリンク
スポンサーリンク
スポンサーリンク

シェアする

フォローする

スポンサーリンク
スポンサーリンク