0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

もうhtml/templateはいらない!Goに最適なQuicktemplateとは

Posted at

Group191.png

Leapcell: The Best of Serverless Web Hosting

Quicktemplate Template Library の使用ガイド

最近、当社のプロジェクトのコードを整理しているとき、多くのアクティビティのコードが構造的に非常に似ており、提供する機能も似ていることに気付きました。将来の開発を容易にするために、私はコードフレームワークを生成するツールを作成するために時間を費やし、繰り返しの作業を最小限に抑えました。コード自体は複雑ではなく、プロジェクトのコードと密接に関係しているため、ここでは詳細を説明しません。この過程で、Go の標準テンプレートライブラリ text/templatehtml/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.qtpltemplates ディレクトリに保存し、その後 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 の構文構造をサポートしており、ifforfuncimportreturn などがあります。書き方は直接 Go コードを書くのと大きく異ならず、学習コストはほとんどありません。ただし、テンプレートでこれらの構文を使用する場合は、{%%} で囲む必要があり、iffor などは endifendfor を追加して明確に終了を示す必要があります。

変数

上で、{%s name %} を使用して渡されたパラメータ name をレンダリングする方法を見ました。namestring 型であるため、{% の後に 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 %}。引用符は &quot; にエスケープされます。
  • 文字列:{%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: &quot;hello&quot;, 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())
}

qtcWrite* メソッドを生成し、このメソッドは 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

brandpic7.png

🚀 好きな言語で構築する

JavaScript、Python、Go、または Rust で簡単に開発できます。

🌍 無料で無制限のプロジェクトをデプロイする

使用する分だけ支払います — リクエストがなければ、請求はありません。

⚡ 使った分だけ支払い、隠された費用はありません

アイドル料金はなく、シームレスなスケーラビリティが提供されます。

Frame3-withpadding2x.png

📖 ドキュメントを探索する

🔹 Twitter でフォローしてください:@LeapcellHQ

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?