第2の人生の構築ログ

自分の好きなことをやりつつ、インカムもしっかりと。FIRA60 (Financial Independence, Retire Around 60) の実現を目指します。SE を生業としていますが、自分でプログラミングしながら自分が欲しいと思うアプリケーションを作ることが楽しみです。旅行と温泉、音楽と読書は欠かすことができません。

Go 言語の html/template で独自関数を使う

f:id:dr_taka_n:20191005135149p:plain

Ruby であれば erb、Java であれば jsp といったように各言語にHTML(/text) へのコードの埋め込みが可能なテンプレートエンジンが用意されています。Go にもテンプレートエンジンがあり、HTML には html/template が使えます。

まぁ、View であるテンプレートへのコードの埋め込みは最低限、質素でいいと思うのですが、それにしても erb などに慣れてしまっていると、Go のテンプレートはえっ?これだけしかできないの??とちょっとビックリするかもしれません。。。四則演算すら標準では用意されていないです。ヘルパー関数が多少は必要な時はあるのではないでしょうか。

ただ、テンプレートに独自に定義した関数を使えるようにする仕組みは用意されていますので、必要なものは追加できます。そのやり方のメモになります。

足し算を行うadd という関数を用意してテンプレート側で利用できるようにします。

用意するのは2ファイルです。

$ tree
.
├── hello.html
└── main.go

まずは、main.go

package main

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

type Params struct {
    I int
    J int
}

func helloTemplate(w http.ResponseWriter, r *http.Request) {
    // 関数の定義とマッピング
    funcMap := template.FuncMap{
        "add": func(i, j int) int { return i + j },
    }
    t := template.Must(template.New("hello.html").Funcs(funcMap).ParseFiles("hello.html"))
    params := Params{I: 1, J: 2}
    err := t.Execute(w, params)
    if err != nil {
        panic(err)
    }
}

func main() {
    http.HandleFunc("/helloTmpl", helloTemplate)

    port := os.Getenv("PORT")
    if port == "" {
        port = "8080"
    }
    log.Printf("Listening on port %s\n", port)
    log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil))
}

template.FuncMap 型は、関数に名前を付けた map になります。

type FuncMap map[string]interface{}

main.go では、"add" という名前で、2つのint 型の引数を取り、その和をintで返す無名関数 func(i, j int) int { return i + j } を値として登録しています。 この FuncMap マップを引数に取る Template 構造体の Funcs メソッドでテンプレート(Template)に登録しています。

これでテンプレートからは、add という関数名で呼び出せるようになります。

ではテンプレートのhello.htmlです。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>Hello</title>
</head>
<body>
<section>
    <h1>Hello, World!</h1>
    <p>テンプレートに渡された数値 {{ .I }} と {{ .J }} の足し算の結果は {{ add .I .J }} です。</p>
</section>
</body>
</html>

起動して確かめてみます。

$ go run main.go

curl でつつきます。

$ curl -X GET localhost:8080/helloTmpl
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>Hello</title>
</head>
<body>
<section>
    <h1>Hello, World!</h1>
    <p>テンプレートに渡された数値 1 と 2 の足し算の結果は 3 です。</p>
</section>
</body>
</html>

main.go で定義した関数がテンプレートで正しく使えたようです。

本日は以上です。


The Go gopher was designed by Renée French.