Leapcell: The Best of Serverless Web Hosting
Quicktemplate Template Library の使用ガイド
最近、当社のプロジェクトのコードを整理しているとき、多くのアクティビティのコードが構造的に非常に似ており、提供する機能も似ていることに気付きました。将来の開発を容易にするために、私はコードフレームワークを生成するツールを作成するために時間を費やし、繰り返しの作業を最小限に抑えました。コード自体は複雑ではなく、プロジェクトのコードと密接に関係しているため、ここでは詳細を説明しません。この過程で、Go の標準テンプレートライブラリ text/template
と html/template
はかなり制限があり、使いにくいことがわかりました。GitHub を通じて、機能が強力で、構文がシンプルで、使いやすいサードパーティのテンプレートライブラリ quicktemplate
を学びました。今日は、quicktemplate
を紹介します。
クイックスタート
本文のコードは Go Modules を使用しています。
プロジェクトの初期化
まず、コードディレクトリを作成して初期化します:
$ mkdir quicktemplate && cd quicktemplate
$ go mod init github.com/leapcell/quicktemplate
依存関係のインストール
quicktemplate
は私たちが書くテンプレートコードを Go 言語のコードに変換します。そのため、quicktemplate
パッケージと qtc
というコンパイラをインストールする必要があります:
$ go get -u github.com/valyala/quicktemplate
$ go get -u github.com/valyala/quicktemplate/qtc
テンプレートファイルの作成
まず、quicktemplate
形式のテンプレートファイルを作成する必要があります。テンプレートファイルのデフォルトの拡張子は .qtpl
です。ここで、簡単なテンプレートファイル greeting.qtpl
を作成しました:
関数の外のすべてのテキストはコメントとして扱われます。
{% func Greeting(name string, count int) %}
{% for i := 0; i < count; i++ %}
Hello, {%s name %}
{% endfor %}
{% endfunc %}
テンプレート構文の説明
テンプレート構文は非常にシンプルです。以下の 2 点を簡単に理解すれば十分です:
- テンプレートは関数を単位としています。関数は任意の型と任意の数のパラメータを受け取ることができ、これらのパラメータは関数内で使用することができます。関数の外のすべてのテキストはコメントであり、
qtc
コンパイラはコメントを無視します。 - 関数内の内容は、構文構造以外はレンダリングされたテキストとしてそのまま出力されます。スペースや改行も含みます。
テンプレートの生成と使用
greeting.qtpl
を templates
ディレクトリに保存し、その後 qtc
コマンドを実行します。このコマンドにより、対応する Go ファイル greeting.qtpl.go
が生成され、パッケージ名は templates
です。これで、このテンプレートを使用することができます:
package main
import (
"fmt"
"github.com/leapcell/quicktemplate/get-started/templates"
)
func main() {
fmt.Println(templates.Greeting("leapcell", 5))
}
コードの実行
テンプレート関数を呼び出し、パラメータを渡して、レンダリングされたテキストを返します:
$ go run .
出力結果:
Hello, leapcell
Hello, leapcell
Hello, leapcell
Hello, leapcell
Hello, leapcell
{%s name %}
はテキストの置換を行い、{% for %}
はループして繰り返しのテキストを生成します。出力に複数のスペースや改行が表示されるのは、関数内の構文構造以外は、スペースや改行を含め、他の内容はそのまま保持されるからです。
注意事項
quicktemplate
はテンプレートを Go コードに変換して使用するため、テンプレートを変更した場合は、必ず qtc
コマンドを最初に実行して Go コードを再生成する必要があります。そうしないと、変更内容が有効になりません。
構文構造
quicktemplate
は一般的な Go の構文構造をサポートしており、if
、for
、func
、import
、return
などがあります。書き方は直接 Go コードを書くのと大きく異ならず、学習コストはほとんどありません。ただし、テンプレートでこれらの構文を使用する場合は、{%
と %}
で囲む必要があり、if
、for
などは endif
、endfor
を追加して明確に終了を示す必要があります。
変数
上で、{%s name %}
を使用して渡されたパラメータ name
をレンダリングする方法を見ました。name
は string
型であるため、{%
の後に s
を使用して型を指定しています。quicktemplate
は他の型の値もサポートしています:
- 整数:
{%d int %}
,{%dl int64 %}
,{%dul uint64 %}
。 - 浮動小数点数:
{%f float %}
。出力精度も設定でき、{%f.precision float %}
を使用します。例えば、{%f.2 1.2345 %}
は1.23
を出力します。 - バイトスライス (
[]byte
):{%z bytes %}
。 - 文字列:
{%q str %}
またはバイトスライス:{%qz bytes %}
。引用符は"
にエスケープされます。 - 文字列:
{%j str %}
またはバイトスライス:{%jz bytes %}
。引用符はありません。 - URL エンコード:
{%u str %}
,{%uz bytes %}
。 -
{%v anything %}
:出力はfmt.Sprintf("%v", anything)
と同等です。
サンプルコード
まず、テンプレートを作成します:
{% func Types(a int, b float64, c []byte, d string) %}
int: {%d a %}, float64: {%f.2 b %}, bytes: {%z c %}, string with quotes: {%q d %}, string without quotes: {%j d %}.
{% endfunc %}
次に、それを使用します:
func main() {
fmt.Println(templates.Types(1, 5.75, []byte{'a', 'b', 'c'}, "hello"))
}
実行します:
$ go run .
出力結果:
int: 1, float64: 5.75, bytes: abc, string with quotes: "hello", string without quotes: hello.
関数の呼び出し
quicktemplate
はテンプレート内でテンプレート関数や標準ライブラリの関数を呼び出すことをサポートしています。qtc
は直接 Go コードを生成するため、同じディレクトリ内に独自の関数を書いて、テンプレートから呼び出すこともできます。テンプレート A で定義された関数は、テンプレート B で定義された関数を呼び出すこともできます。
カスタム関数の定義
まず、templates
ディレクトリに rank.go
ファイルを作成し、スコアを受け取り、評価を返す Rank
関数を定義します:
package templates
func Rank(score int) string {
if score >= 90 {
return "A"
} else if score >= 80 {
return "B"
} else if score >= 70 {
return "C"
} else if score >= 60 {
return "D"
} else {
return "E"
}
}
テンプレート内でカスタム関数を呼び出す
次に、この関数をテンプレート内で呼び出すことができます:
{% import "fmt" %}
{% func ScoreList(name2score map[string]int) %}
{% for name, score := range name2score %}
{%s fmt.Sprintf("%s: score-%d rank-%s", name, score, Rank(score)) %}
{% endfor %}
{% endfunc %}
テンプレートのコンパイルと使用
テンプレートをコンパイルします:
$ qtc
プログラムを書きます:
func main() {
name2score := make(map[string]int)
name2score["leapcell"] = 85
name2score["bob"] = 86
name2score["alice"] = 22
fmt.Println(templates.ScoreList(name2score))
}
プログラムを実行して出力します:
$ go run .
出力結果:
leapcell: score-85 rank-B
bob: score-86 rank-A
alice: score-22 rank-E
テンプレート内で fmt
パッケージを使用しているため、{% import %}
を使用してパッケージを最初にインポートする必要があります。テンプレート内で別のテンプレートの関数を呼び出す方法も似ています。なぜなら、テンプレートは最終的に Go コードに変換され、Go コード内に同じシグネチャの関数が存在するからです。
ウェブアプリケーション
quicktemplate
はよく HTML ページのテンプレートを書くために使用されます:
{% func Index(name string) %}
<html>
<head>
<title>Awesome Web</title>
</head>
<body>
<h1>Hi, {%s name %}
<p>Welcome to the awesome web!!!</p>
</body>
</html>
{% endfunc %}
次に、簡単なウェブサーバを書きます:
func index(w http.ResponseWriter, r *http.Request) {
templates.WriteIndex(w, r.FormValue("name"))
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", index)
server := &http.Server{
Handler: mux,
Addr: ":8080",
}
log.Fatal(server.ListenAndServe())
}
qtc
は Write*
メソッドを生成し、このメソッドは io.Writer
型のパラメータを受け取ります。テンプレートをレンダリングした結果は、この io.Writer
に書き込まれます。私たちは http.ResponseWriter
を直接パラメータとして渡すことができ、非常に便利です。
ウェブサーバの実行
$ qtc
$ go run .
ブラウザで localhost:8080?name=leapcell
を入力して結果を表示します。
まとめ
quicktemplate
には少なくとも以下の 3 つの利点があります:
- 構文は Go 言語と非常に似ており、学習コストはほとんどありません。
- 最初に Go に変換され、レンダリング速度が非常に速く、標準ライブラリ
html/template
の 20 倍以上速いです。 - セキュリティ上の理由から、いくつかのエンコードを行い、攻撃を回避します。
Leapcell: The Best of Serverless Web Hosting
最後に、Go サービスのデプロイに最適なプラットフォームをお勧めします:Leapcell
🚀 好きな言語で構築する
JavaScript、Python、Go、または Rust で簡単に開発できます。
🌍 無料で無制限のプロジェクトをデプロイする
使用する分だけ支払います — リクエストがなければ、請求はありません。
⚡ 使った分だけ支払い、隠された費用はありません
アイドル料金はなく、シームレスなスケーラビリティが提供されます。
🔹 Twitter でフォローしてください:@LeapcellHQ