技術向上

プログラミングの学び、気になるテクノロジーやビジネストレンドを発信

htmlのtemplate【Go】

概要

http.ResponseWriterにセットする内容量が多い場合(複数行に渡るhtml記述)、
template機能を使うべきです。

事前にhtmlファイル(今回はview.html)を同階層に作成し、
後で示すコードを記述したmain.goを実行します。


htmlファイルの記述

まずはtemplateとなるhtmlファイルの記述方法です。
基本的には通常のhtmlと同じ書き方ですが、
goファイルから渡されるPage structの中身などを表示したい場合に、工夫が必要です。

<!-- 「.<フィールド名>」で、http.ResponseWriterに登録したgoファイルの変数を表示 -->
<h1>{{.Title}}</h1>

<!-- editは別途必要。文字列の中にも「.<フィールド名>」を記述できる -->
<p><a href="/edit/{{.Title}}">Edit</a></p>

<!-- 「printf %s .<フィールド名>」で、byte配列をキャスト -->
<div>{{printf "%s" .Body}}</div>

上記のように、structの場合、「.<フィールド名>」と記述すれば、
template.ParseFiles("~.html").Execute(w http.ResponseWriter, i interface{}) で登録した
goファイルからの内容を表示することができます。
ただし、byte配列の場合は「printf %s .<フィールド名>」としてstring型にキャストします。

goファイルの記述

http.HandleFunc()で登録するHandler関数の処理を
templateを使うように記述します。

type Page struct {
    Title string
    Body  []byte
}

func load(title string) (*Page, error) {
    filename := title + ".txt"
    body, err := ioutil.ReadFile(filename)
    if err != nil {
        return nil, err
    }
    return &Page{Title: title, Body: body}, nil
}

func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
    t, _ := template.ParseFiles(tmpl + ".html")    // 同階層にあるhtmlファイルを読み込む
    t.Execute(w, p)    // 読み込んだ内容をhttp.ResponseWriterに登録する
}

func viewHandler(w http.ResponseWriter, r *http.Request) {
    title := r.URL.Path[len("/view/"):]
    p, err := load(title)
    if err != nil {
        log.Fatalln(err)
    }
    // fmt.Fprintf(w, "<h1>%s</h1><div>%s</div>", p.Title, p.Body)    // この書き方だと、内容が多い場合に不便
    renderTemplate(w, "view", p)
}

func main() {
    http.HandleFunc("/view/", viewHandler)
    log.Fatalln(http.ListenAndServe(":8080", nil))
}


関連記事 tech-up.hatenablog.com